@rotorsoft/act-sqlite 1.20.3 → 1.21.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/.tsbuildinfo +1 -1
- package/dist/@types/sqlite-store.d.ts +12 -0
- package/dist/@types/sqlite-store.d.ts.map +1 -1
- package/dist/index.cjs +55 -113
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +55 -113
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -654,30 +654,45 @@ var SqliteStore = class {
|
|
|
654
654
|
// Cleared by ack/block/reset/unblock. See {@link Store.defer}.
|
|
655
655
|
async defer(input, deferred_at) {
|
|
656
656
|
const at_iso = new Date(deferred_at).toISOString();
|
|
657
|
+
try {
|
|
658
|
+
return await this._update(input, "SET deferred_at = ?, retry = -1", [
|
|
659
|
+
at_iso
|
|
660
|
+
]);
|
|
661
|
+
} catch (e) {
|
|
662
|
+
throw new StoreError("defer", { cause: e });
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
/**
|
|
666
|
+
* Runs `UPDATE streams <set>` on the streams named by `input`, in one
|
|
667
|
+
* write transaction that rolls back on failure. An explicit list is
|
|
668
|
+
* de-duplicated, so a repeated name counts once (matching PG's set-based
|
|
669
|
+
* `stream = ANY(...)`), and updated one name per statement, so a long list
|
|
670
|
+
* never meets SQLite's bound-parameter limit. `set` and `where` bind
|
|
671
|
+
* `params` in order; libSQL `?` placeholders are positional and can't be
|
|
672
|
+
* reused, so a value used twice is passed twice.
|
|
673
|
+
*
|
|
674
|
+
* @returns Count of rows updated.
|
|
675
|
+
*/
|
|
676
|
+
async _update(input, set, params = [], where) {
|
|
677
|
+
const selections = Array.isArray(input) ? [...new Set(input)].map((stream) => ({
|
|
678
|
+
clause: "stream = ?",
|
|
679
|
+
args: [stream]
|
|
680
|
+
})) : [this._filter_clause(input)];
|
|
657
681
|
const tx = await this.client.transaction("write");
|
|
658
682
|
try {
|
|
659
683
|
let count = 0;
|
|
660
|
-
|
|
661
|
-
for (const stream of new Set(input)) {
|
|
662
|
-
const r = await tx.execute({
|
|
663
|
-
sql: `UPDATE streams SET deferred_at = ?, retry = -1 WHERE stream = ?`,
|
|
664
|
-
args: [at_iso, stream]
|
|
665
|
-
});
|
|
666
|
-
count += r.rowsAffected;
|
|
667
|
-
}
|
|
668
|
-
} else {
|
|
669
|
-
const { clause, args } = this._filter_clause(input);
|
|
684
|
+
for (const { clause, args } of selections) {
|
|
670
685
|
const r = await tx.execute({
|
|
671
|
-
sql: `UPDATE streams
|
|
672
|
-
args: [
|
|
686
|
+
sql: `UPDATE streams ${set} WHERE ${where ? `${where} AND ` : ""}${clause}`,
|
|
687
|
+
args: [...params, ...args]
|
|
673
688
|
});
|
|
674
|
-
count
|
|
689
|
+
count += r.rowsAffected;
|
|
675
690
|
}
|
|
676
691
|
await tx.commit();
|
|
677
692
|
return count;
|
|
678
693
|
} catch (e) {
|
|
679
694
|
await tx.rollback();
|
|
680
|
-
throw
|
|
695
|
+
throw e;
|
|
681
696
|
}
|
|
682
697
|
}
|
|
683
698
|
/**
|
|
@@ -718,103 +733,32 @@ var SqliteStore = class {
|
|
|
718
733
|
return { clause: conditions.length ? conditions.join(" AND ") : "1", args };
|
|
719
734
|
}
|
|
720
735
|
// --- reset: transactional, accepts names or filter ---
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
if (Array.isArray(input)) {
|
|
728
|
-
for (const stream of new Set(input)) {
|
|
729
|
-
const r = await tx.execute({
|
|
730
|
-
sql: `UPDATE streams ${set_clause} WHERE stream = ?`,
|
|
731
|
-
args: [stream]
|
|
732
|
-
});
|
|
733
|
-
count += r.rowsAffected;
|
|
734
|
-
}
|
|
735
|
-
} else {
|
|
736
|
-
const { clause, args } = this._filter_clause(input);
|
|
737
|
-
const r = await tx.execute({
|
|
738
|
-
sql: `UPDATE streams ${set_clause} WHERE ${clause}`,
|
|
739
|
-
args
|
|
740
|
-
});
|
|
741
|
-
count = r.rowsAffected;
|
|
742
|
-
}
|
|
743
|
-
await tx.commit();
|
|
744
|
-
return count;
|
|
745
|
-
} catch (e) {
|
|
746
|
-
await tx.rollback();
|
|
747
|
-
throw e;
|
|
748
|
-
}
|
|
736
|
+
reset(input) {
|
|
737
|
+
return this._update(
|
|
738
|
+
input,
|
|
739
|
+
`SET at = -1, retry = -1, blocked = 0, error = '',
|
|
740
|
+
leased_by = NULL, leased_until = NULL, deferred_at = NULL`
|
|
741
|
+
);
|
|
749
742
|
}
|
|
750
743
|
// --- unblock: clear blocked + retry + lease without touching watermark ---
|
|
751
744
|
// `retry = -1` so claim's post-bump returns retry=0 (first attempt),
|
|
752
|
-
// matching the InMemoryStore convention.
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
WHERE stream = ? AND blocked = 1`,
|
|
764
|
-
args: [stream]
|
|
765
|
-
});
|
|
766
|
-
count += r.rowsAffected;
|
|
767
|
-
}
|
|
768
|
-
} else {
|
|
769
|
-
const { clause, args } = this._filter_clause({
|
|
770
|
-
...input,
|
|
771
|
-
blocked: true
|
|
772
|
-
});
|
|
773
|
-
const r = await tx.execute({
|
|
774
|
-
sql: `UPDATE streams ${set_clause} WHERE ${clause}`,
|
|
775
|
-
args
|
|
776
|
-
});
|
|
777
|
-
count = r.rowsAffected;
|
|
778
|
-
}
|
|
779
|
-
await tx.commit();
|
|
780
|
-
return count;
|
|
781
|
-
} catch (e) {
|
|
782
|
-
await tx.rollback();
|
|
783
|
-
throw e;
|
|
784
|
-
}
|
|
745
|
+
// matching the InMemoryStore convention. Always restricted to blocked
|
|
746
|
+
// rows, whatever the filter says: there is no use case for "unblock
|
|
747
|
+
// unblocked streams."
|
|
748
|
+
unblock(input) {
|
|
749
|
+
return this._update(
|
|
750
|
+
Array.isArray(input) ? input : { ...input, blocked: void 0 },
|
|
751
|
+
`SET retry = -1, blocked = 0, error = '',
|
|
752
|
+
leased_by = NULL, leased_until = NULL, deferred_at = NULL`,
|
|
753
|
+
[],
|
|
754
|
+
"blocked = 1"
|
|
755
|
+
);
|
|
785
756
|
}
|
|
786
757
|
// --- query_streams: read-only introspection with filters ---
|
|
787
758
|
async query_streams(callback, query) {
|
|
788
759
|
const limit = query?.limit ?? 100;
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
if (query?.stream !== void 0) {
|
|
792
|
-
if (query.stream_exact) {
|
|
793
|
-
sql += " AND stream = ?";
|
|
794
|
-
args.push(query.stream);
|
|
795
|
-
} else {
|
|
796
|
-
sql += " AND stream GLOB ?";
|
|
797
|
-
args.push(streamPatternToGlob(query.stream));
|
|
798
|
-
}
|
|
799
|
-
}
|
|
800
|
-
if (query?.source !== void 0) {
|
|
801
|
-
sql += " AND source IS NOT NULL";
|
|
802
|
-
if (query.source_exact) {
|
|
803
|
-
sql += " AND source = ?";
|
|
804
|
-
args.push(query.source);
|
|
805
|
-
} else {
|
|
806
|
-
sql += " AND source GLOB ?";
|
|
807
|
-
args.push(streamPatternToGlob(query.source));
|
|
808
|
-
}
|
|
809
|
-
}
|
|
810
|
-
if (query?.blocked !== void 0) {
|
|
811
|
-
sql += " AND blocked = ?";
|
|
812
|
-
args.push(query.blocked ? 1 : 0);
|
|
813
|
-
}
|
|
814
|
-
if (query?.lane !== void 0) {
|
|
815
|
-
sql += " AND lane = ?";
|
|
816
|
-
args.push(query.lane);
|
|
817
|
-
}
|
|
760
|
+
const { clause, args } = this._filter_clause(query ?? {});
|
|
761
|
+
let sql = `SELECT stream, source, at, retry, blocked, error, leased_by, leased_until, priority, lane, deferred_at, correlated_at FROM streams WHERE ${clause}`;
|
|
818
762
|
if (query?.after !== void 0) {
|
|
819
763
|
sql += " AND stream > ?";
|
|
820
764
|
args.push(query.after);
|
|
@@ -1073,15 +1017,13 @@ var SqliteStore = class {
|
|
|
1073
1017
|
return out;
|
|
1074
1018
|
}
|
|
1075
1019
|
// --- prioritize: bulk priority update with filter ---
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
});
|
|
1084
|
-
return result.rowsAffected;
|
|
1020
|
+
prioritize(filter, priority) {
|
|
1021
|
+
return this._update(
|
|
1022
|
+
filter,
|
|
1023
|
+
"SET priority = ?",
|
|
1024
|
+
[priority, priority],
|
|
1025
|
+
"priority <> ?"
|
|
1026
|
+
);
|
|
1085
1027
|
}
|
|
1086
1028
|
// --- truncate: transactional delete + seed ---
|
|
1087
1029
|
// Windowed targets (`before` set) prune the prefix below the closest safe
|