feat: add engine and store snapshot/restore for restart resilience
This commit is contained in:
@@ -1,8 +1,9 @@
|
||||
"use strict";
|
||||
|
||||
class AudioAccessStore {
|
||||
constructor() {
|
||||
this.grants = new Map();
|
||||
constructor(initialState) {
|
||||
const entries = Object.entries((initialState && initialState.grants) || {});
|
||||
this.grants = new Map(entries.map(([audioId, userIds]) => [audioId, new Set(userIds)]));
|
||||
}
|
||||
|
||||
_key(audioId) {
|
||||
@@ -71,6 +72,15 @@ class AudioAccessStore {
|
||||
this.grantAccess(audio.id, userId);
|
||||
return { unlocked: true, charged: audio.creditsCharged };
|
||||
}
|
||||
|
||||
exportState() {
|
||||
const grants = {};
|
||||
for (const [audioId, users] of this.grants.entries()) {
|
||||
grants[audioId] = Array.from(users.values());
|
||||
}
|
||||
|
||||
return { grants };
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
|
||||
@@ -6,17 +6,21 @@ const { calculateCredits } = require("./credits");
|
||||
const { extractArticleFromParent } = require("./article");
|
||||
|
||||
class XArtAudioEngine {
|
||||
constructor({ creditConfig }) {
|
||||
constructor({ creditConfig, initialState }) {
|
||||
this.creditConfig = creditConfig;
|
||||
this.wallets = new WalletStore();
|
||||
this.access = new AudioAccessStore();
|
||||
this.wallets = new WalletStore(initialState && initialState.wallets);
|
||||
this.access = new AudioAccessStore(initialState && initialState.access);
|
||||
|
||||
this.jobs = new Map();
|
||||
this.assets = new Map();
|
||||
this.mentions = new Map();
|
||||
this.jobs = new Map(Object.entries((initialState && initialState.jobs) || {}));
|
||||
this.assets = new Map(Object.entries((initialState && initialState.assets) || {}));
|
||||
this.mentions = new Map(Object.entries((initialState && initialState.mentions) || {}));
|
||||
|
||||
this.nextJobId = 1;
|
||||
this.nextAssetId = 1;
|
||||
this.nextJobId = Number.isInteger(initialState && initialState.nextJobId)
|
||||
? initialState.nextJobId
|
||||
: 1;
|
||||
this.nextAssetId = Number.isInteger(initialState && initialState.nextAssetId)
|
||||
? initialState.nextAssetId
|
||||
: 1;
|
||||
}
|
||||
|
||||
topUpCredits(userId, amount, idempotencyKey) {
|
||||
@@ -166,6 +170,18 @@ class XArtAudioEngine {
|
||||
wallet: this.wallets,
|
||||
});
|
||||
}
|
||||
|
||||
exportState() {
|
||||
return {
|
||||
wallets: this.wallets.exportState(),
|
||||
access: this.access.exportState(),
|
||||
jobs: Object.fromEntries(this.jobs.entries()),
|
||||
assets: Object.fromEntries(this.assets.entries()),
|
||||
mentions: Object.fromEntries(this.mentions.entries()),
|
||||
nextJobId: this.nextJobId,
|
||||
nextAssetId: this.nextAssetId,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
|
||||
@@ -1,11 +1,19 @@
|
||||
"use strict";
|
||||
|
||||
class WalletStore {
|
||||
constructor() {
|
||||
this.balances = new Map();
|
||||
this.transactions = [];
|
||||
this.byIdempotencyKey = new Map();
|
||||
this.nextId = 1;
|
||||
constructor(initialState) {
|
||||
this.balances = new Map(Object.entries((initialState && initialState.balances) || {}));
|
||||
this.transactions = Array.isArray(initialState && initialState.transactions)
|
||||
? [...initialState.transactions]
|
||||
: [];
|
||||
this.byIdempotencyKey = new Map(
|
||||
this.transactions
|
||||
.filter((tx) => tx.idempotencyKey)
|
||||
.map((tx) => [tx.idempotencyKey, tx]),
|
||||
);
|
||||
this.nextId = Number.isInteger(initialState && initialState.nextId)
|
||||
? initialState.nextId
|
||||
: (this.transactions.length + 1);
|
||||
}
|
||||
|
||||
getBalance(userId) {
|
||||
@@ -63,6 +71,14 @@ class WalletStore {
|
||||
this.balances.set(userId, newBalance);
|
||||
return tx;
|
||||
}
|
||||
|
||||
exportState() {
|
||||
return {
|
||||
balances: Object.fromEntries(this.balances.entries()),
|
||||
transactions: [...this.transactions],
|
||||
nextId: this.nextId,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
|
||||
Reference in New Issue
Block a user