@cloudbitmaps/core 0.4.1 → 0.6.0
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/index.cjs +38 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +49 -8
- package/dist/index.d.ts +49 -8
- package/dist/index.js +38 -7
- package/dist/index.js.map +1 -1
- package/dist/mysql/index.cjs.map +1 -1
- package/dist/mysql/index.js.map +1 -1
- package/dist/postgres/index.cjs.map +1 -1
- package/dist/postgres/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -2184,6 +2184,7 @@ function writeCrbmGeneration(driver, key, chunks, options = {}) {
|
|
|
2184
2184
|
const writer = new CrbmWriter(sink, { generation: key.generation, crypto: options.crypto });
|
|
2185
2185
|
for (const { chunkKey, bitmap } of sorted) {
|
|
2186
2186
|
if (bitmap.isEmpty) continue;
|
|
2187
|
+
bitmap.optimize?.();
|
|
2187
2188
|
await writer.addChunk(chunkKey, bitmap.serialize(), bitmap.size);
|
|
2188
2189
|
const pause = tick();
|
|
2189
2190
|
if (pause !== null) await pause;
|
|
@@ -2199,6 +2200,7 @@ async function writeCrbmGenerationStream(driver, key, chunks, options = {}) {
|
|
|
2199
2200
|
const writer = new CrbmWriter(sink, { generation: key.generation, crypto: options.crypto });
|
|
2200
2201
|
for await (const { chunkKey, bitmap } of chunks) {
|
|
2201
2202
|
if (bitmap.isEmpty) continue;
|
|
2203
|
+
bitmap.optimize?.();
|
|
2202
2204
|
await writer.addChunk(chunkKey, bitmap.serialize(), bitmap.size);
|
|
2203
2205
|
chunkKeys.push(chunkKey);
|
|
2204
2206
|
cardinality += bitmap.size;
|
|
@@ -2218,6 +2220,10 @@ async function publishGeneration(registry, key, options = {}) {
|
|
|
2218
2220
|
currentGen: key.generation,
|
|
2219
2221
|
wrappedDeks: options.wrappedDeks
|
|
2220
2222
|
});
|
|
2223
|
+
} else if (record.status === "destroyed") {
|
|
2224
|
+
throw new ValidationError(
|
|
2225
|
+
`segment "${key.segment}" was destroyed (crypto-shredded) while generation ${key.generation} was being written \u2014 refusing to publish it; the written object is unreadable. Use a new segment.`
|
|
2226
|
+
);
|
|
2221
2227
|
} else if (record.currentGen > key.generation) {
|
|
2222
2228
|
return false;
|
|
2223
2229
|
} else if (record.currentGen === key.generation) {
|
|
@@ -3983,7 +3989,22 @@ async function eraseNamespace(namespace, deps, options) {
|
|
|
3983
3989
|
const destroyed = [];
|
|
3984
3990
|
let segmentsShredded = 0;
|
|
3985
3991
|
for (const ref of refs) {
|
|
3986
|
-
|
|
3992
|
+
let result;
|
|
3993
|
+
try {
|
|
3994
|
+
result = await shredSegment(ref, deps, options.allowCleartext ?? false);
|
|
3995
|
+
} catch (err) {
|
|
3996
|
+
result = {
|
|
3997
|
+
segment: ref.segment,
|
|
3998
|
+
namespace: ref.namespace,
|
|
3999
|
+
destroyed: false,
|
|
4000
|
+
cryptoShredded: false,
|
|
4001
|
+
reason: isWriteConflictError(err) ? "contended" : `failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
4002
|
+
// Deliberately 0, and not a partial count. `eraseWarm` may have deleted rows before it threw, but the
|
|
4003
|
+
// erase did not complete as a unit, so a partial figure on a failed entry would invite reading it as
|
|
4004
|
+
// progress toward a destruction that did not happen. The attestation that matters is `destroyed`.
|
|
4005
|
+
warmRowsDeleted: 0
|
|
4006
|
+
};
|
|
4007
|
+
}
|
|
3987
4008
|
destroyed.push(result);
|
|
3988
4009
|
if (result.cryptoShredded) {
|
|
3989
4010
|
segmentsShredded += 1;
|
|
@@ -4046,12 +4067,13 @@ async function shredSegment(ref, deps, allowCleartext) {
|
|
|
4046
4067
|
}
|
|
4047
4068
|
async function eraseWarm(warm, ref) {
|
|
4048
4069
|
let deleted = 0;
|
|
4070
|
+
let conflicts = 0;
|
|
4049
4071
|
for (let pass = 0; pass < MAX_WARM_PASSES; pass++) {
|
|
4072
|
+
conflicts = 0;
|
|
4050
4073
|
const rows = [];
|
|
4051
4074
|
for await (const row of warm.listChunks(ref))
|
|
4052
4075
|
rows.push({ chunkKey: row.chunkKey, token: row.token });
|
|
4053
4076
|
if (rows.length === 0) break;
|
|
4054
|
-
let conflicts = 0;
|
|
4055
4077
|
for (const { chunkKey, token } of rows) {
|
|
4056
4078
|
const chunkRef = { namespace: ref.namespace, segment: ref.segment, chunkKey };
|
|
4057
4079
|
try {
|
|
@@ -4064,6 +4086,11 @@ async function eraseWarm(warm, ref) {
|
|
|
4064
4086
|
}
|
|
4065
4087
|
if (conflicts === 0) break;
|
|
4066
4088
|
}
|
|
4089
|
+
if (conflicts > 0) {
|
|
4090
|
+
throw new WriteConflictError(
|
|
4091
|
+
`destroySegment: ${conflicts} warm row(s) of "${ref.segment}" were rewritten during every one of ${MAX_WARM_PASSES} erase passes \u2014 the segment was NOT destroyed and its cleartext warm deltas are still readable. Stop writes to this segment and retry.`
|
|
4092
|
+
);
|
|
4093
|
+
}
|
|
4067
4094
|
return deleted;
|
|
4068
4095
|
}
|
|
4069
4096
|
|
|
@@ -4194,11 +4221,15 @@ var RetryingWarmDriver = class {
|
|
|
4194
4221
|
this.deps
|
|
4195
4222
|
);
|
|
4196
4223
|
if (started.first.done === true) return;
|
|
4197
|
-
|
|
4198
|
-
|
|
4199
|
-
|
|
4200
|
-
|
|
4201
|
-
|
|
4224
|
+
try {
|
|
4225
|
+
yield started.first.value;
|
|
4226
|
+
for (; ; ) {
|
|
4227
|
+
const next = await started.iterator.next();
|
|
4228
|
+
if (next.done === true) return;
|
|
4229
|
+
yield next.value;
|
|
4230
|
+
}
|
|
4231
|
+
} finally {
|
|
4232
|
+
await started.iterator.return?.();
|
|
4202
4233
|
}
|
|
4203
4234
|
}
|
|
4204
4235
|
};
|