s3db.js 10.0.13 → 10.0.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/s3db.cjs.js +114 -7
- package/dist/s3db.cjs.js.map +1 -1
- package/dist/s3db.es.js +114 -7
- package/dist/s3db.es.js.map +1 -1
- package/package.json +1 -1
- package/src/plugins/cache.plugin.js +19 -7
- package/src/plugins/eventual-consistency.plugin.js +159 -11
- package/src/plugins/backup.plugin.js.backup +0 -1026
package/dist/s3db.cjs.js
CHANGED
|
@@ -3926,6 +3926,14 @@ class CachePlugin extends Plugin {
|
|
|
3926
3926
|
];
|
|
3927
3927
|
for (const method of cacheMethods) {
|
|
3928
3928
|
resource.useMiddleware(method, async (ctx, next) => {
|
|
3929
|
+
let skipCache = false;
|
|
3930
|
+
const lastArg = ctx.args[ctx.args.length - 1];
|
|
3931
|
+
if (lastArg && typeof lastArg === "object" && lastArg.skipCache === true) {
|
|
3932
|
+
skipCache = true;
|
|
3933
|
+
}
|
|
3934
|
+
if (skipCache) {
|
|
3935
|
+
return await next();
|
|
3936
|
+
}
|
|
3929
3937
|
let key;
|
|
3930
3938
|
if (method === "getMany") {
|
|
3931
3939
|
key = await resource.cacheKeyFor({ action: method, params: { ids: ctx.args[0] } });
|
|
@@ -5113,10 +5121,6 @@ class EventualConsistencyPlugin extends Plugin {
|
|
|
5113
5121
|
return recordOk && record ? record[this.config.field] || 0 : 0;
|
|
5114
5122
|
}
|
|
5115
5123
|
try {
|
|
5116
|
-
const [recordOk, recordErr, record] = await tryFn(
|
|
5117
|
-
() => this.targetResource.get(originalId)
|
|
5118
|
-
);
|
|
5119
|
-
const currentValue = recordOk && record ? record[this.config.field] || 0 : 0;
|
|
5120
5124
|
const [ok, err, transactions] = await tryFn(
|
|
5121
5125
|
() => this.transactionResource.query({
|
|
5122
5126
|
originalId,
|
|
@@ -5124,16 +5128,119 @@ class EventualConsistencyPlugin extends Plugin {
|
|
|
5124
5128
|
})
|
|
5125
5129
|
);
|
|
5126
5130
|
if (!ok || !transactions || transactions.length === 0) {
|
|
5131
|
+
const [recordOk, recordErr, record] = await tryFn(
|
|
5132
|
+
() => this.targetResource.get(originalId)
|
|
5133
|
+
);
|
|
5134
|
+
const currentValue2 = recordOk && record ? record[this.config.field] || 0 : 0;
|
|
5127
5135
|
if (this.config.verbose) {
|
|
5128
5136
|
console.log(
|
|
5129
5137
|
`[EventualConsistency] ${this.config.resource}.${this.config.field} - No pending transactions for ${originalId}, skipping`
|
|
5130
5138
|
);
|
|
5131
5139
|
}
|
|
5132
|
-
return
|
|
5140
|
+
return currentValue2;
|
|
5141
|
+
}
|
|
5142
|
+
const [appliedOk, appliedErr, appliedTransactions] = await tryFn(
|
|
5143
|
+
() => this.transactionResource.query({
|
|
5144
|
+
originalId,
|
|
5145
|
+
applied: true
|
|
5146
|
+
})
|
|
5147
|
+
);
|
|
5148
|
+
let currentValue = 0;
|
|
5149
|
+
if (appliedOk && appliedTransactions && appliedTransactions.length > 0) {
|
|
5150
|
+
const [recordExistsOk, recordExistsErr, recordExists] = await tryFn(
|
|
5151
|
+
() => this.targetResource.get(originalId)
|
|
5152
|
+
);
|
|
5153
|
+
if (!recordExistsOk || !recordExists) {
|
|
5154
|
+
if (this.config.verbose) {
|
|
5155
|
+
console.log(
|
|
5156
|
+
`[EventualConsistency] ${this.config.resource}.${this.config.field} - Record ${originalId} doesn't exist, deleting ${appliedTransactions.length} old applied transactions`
|
|
5157
|
+
);
|
|
5158
|
+
}
|
|
5159
|
+
const { results, errors } = await promisePool.PromisePool.for(appliedTransactions).withConcurrency(10).process(async (txn) => {
|
|
5160
|
+
const [deleted] = await tryFn(() => this.transactionResource.delete(txn.id));
|
|
5161
|
+
return deleted;
|
|
5162
|
+
});
|
|
5163
|
+
if (this.config.verbose && errors && errors.length > 0) {
|
|
5164
|
+
console.warn(
|
|
5165
|
+
`[EventualConsistency] ${this.config.resource}.${this.config.field} - Failed to delete ${errors.length} old applied transactions`
|
|
5166
|
+
);
|
|
5167
|
+
}
|
|
5168
|
+
currentValue = 0;
|
|
5169
|
+
} else {
|
|
5170
|
+
appliedTransactions.sort(
|
|
5171
|
+
(a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime()
|
|
5172
|
+
);
|
|
5173
|
+
const hasSetInApplied = appliedTransactions.some((t) => t.operation === "set");
|
|
5174
|
+
if (!hasSetInApplied) {
|
|
5175
|
+
const recordValue = recordExists[this.config.field] || 0;
|
|
5176
|
+
let appliedDelta = 0;
|
|
5177
|
+
for (const t of appliedTransactions) {
|
|
5178
|
+
if (t.operation === "add") appliedDelta += t.value;
|
|
5179
|
+
else if (t.operation === "sub") appliedDelta -= t.value;
|
|
5180
|
+
}
|
|
5181
|
+
const baseValue = recordValue - appliedDelta;
|
|
5182
|
+
const hasExistingAnchor = appliedTransactions.some((t) => t.source === "anchor");
|
|
5183
|
+
if (baseValue !== 0 && !hasExistingAnchor) {
|
|
5184
|
+
const firstTransactionDate = new Date(appliedTransactions[0].timestamp);
|
|
5185
|
+
const cohortInfo = this.getCohortInfo(firstTransactionDate);
|
|
5186
|
+
const anchorTransaction = {
|
|
5187
|
+
id: idGenerator(),
|
|
5188
|
+
originalId,
|
|
5189
|
+
field: this.config.field,
|
|
5190
|
+
value: baseValue,
|
|
5191
|
+
operation: "set",
|
|
5192
|
+
timestamp: new Date(firstTransactionDate.getTime() - 1).toISOString(),
|
|
5193
|
+
// 1ms before first txn to ensure it's first
|
|
5194
|
+
cohortDate: cohortInfo.date,
|
|
5195
|
+
cohortHour: cohortInfo.hour,
|
|
5196
|
+
cohortMonth: cohortInfo.month,
|
|
5197
|
+
source: "anchor",
|
|
5198
|
+
applied: true
|
|
5199
|
+
};
|
|
5200
|
+
await this.transactionResource.insert(anchorTransaction);
|
|
5201
|
+
appliedTransactions.unshift(anchorTransaction);
|
|
5202
|
+
}
|
|
5203
|
+
}
|
|
5204
|
+
currentValue = this.config.reducer(appliedTransactions);
|
|
5205
|
+
}
|
|
5206
|
+
} else {
|
|
5207
|
+
const [recordOk, recordErr, record] = await tryFn(
|
|
5208
|
+
() => this.targetResource.get(originalId)
|
|
5209
|
+
);
|
|
5210
|
+
currentValue = recordOk && record ? record[this.config.field] || 0 : 0;
|
|
5211
|
+
if (currentValue !== 0) {
|
|
5212
|
+
let anchorTimestamp;
|
|
5213
|
+
if (transactions && transactions.length > 0) {
|
|
5214
|
+
const firstPendingDate = new Date(transactions[0].timestamp);
|
|
5215
|
+
anchorTimestamp = new Date(firstPendingDate.getTime() - 1).toISOString();
|
|
5216
|
+
} else {
|
|
5217
|
+
anchorTimestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
5218
|
+
}
|
|
5219
|
+
const cohortInfo = this.getCohortInfo(new Date(anchorTimestamp));
|
|
5220
|
+
const anchorTransaction = {
|
|
5221
|
+
id: idGenerator(),
|
|
5222
|
+
originalId,
|
|
5223
|
+
field: this.config.field,
|
|
5224
|
+
value: currentValue,
|
|
5225
|
+
operation: "set",
|
|
5226
|
+
timestamp: anchorTimestamp,
|
|
5227
|
+
cohortDate: cohortInfo.date,
|
|
5228
|
+
cohortHour: cohortInfo.hour,
|
|
5229
|
+
cohortMonth: cohortInfo.month,
|
|
5230
|
+
source: "anchor",
|
|
5231
|
+
applied: true
|
|
5232
|
+
};
|
|
5233
|
+
await this.transactionResource.insert(anchorTransaction);
|
|
5234
|
+
if (this.config.verbose) {
|
|
5235
|
+
console.log(
|
|
5236
|
+
`[EventualConsistency] ${this.config.resource}.${this.config.field} - Created anchor transaction for ${originalId} with base value ${currentValue}`
|
|
5237
|
+
);
|
|
5238
|
+
}
|
|
5239
|
+
}
|
|
5133
5240
|
}
|
|
5134
5241
|
if (this.config.verbose) {
|
|
5135
5242
|
console.log(
|
|
5136
|
-
`[EventualConsistency] ${this.config.resource}.${this.config.field} - Consolidating ${originalId}: ${transactions.length} pending transactions (current: ${currentValue})`
|
|
5243
|
+
`[EventualConsistency] ${this.config.resource}.${this.config.field} - Consolidating ${originalId}: ${transactions.length} pending transactions (current: ${currentValue} from ${appliedOk && appliedTransactions?.length > 0 ? "applied transactions" : "record"})`
|
|
5137
5244
|
);
|
|
5138
5245
|
}
|
|
5139
5246
|
transactions.sort(
|
|
@@ -12053,7 +12160,7 @@ class Database extends EventEmitter {
|
|
|
12053
12160
|
this.id = idGenerator(7);
|
|
12054
12161
|
this.version = "1";
|
|
12055
12162
|
this.s3dbVersion = (() => {
|
|
12056
|
-
const [ok, err, version] = tryFn(() => true ? "10.0.
|
|
12163
|
+
const [ok, err, version] = tryFn(() => true ? "10.0.15" : "latest");
|
|
12057
12164
|
return ok ? version : "latest";
|
|
12058
12165
|
})();
|
|
12059
12166
|
this.resources = {};
|