velocious 1.0.574 → 1.0.576
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/README.md +17 -3
- package/build/background-jobs/client.js +71 -3
- package/build/background-jobs/job.js +30 -0
- package/build/background-jobs/main.js +100 -14
- package/build/background-jobs/store.js +344 -41
- package/build/background-jobs/types.js +25 -1
- package/build/background-jobs/web/controller.js +1 -0
- package/build/database/advisory-lock-runner.js +27 -17
- package/build/database/drivers/mssql/index.js +98 -3
- package/build/database/record/index.js +10 -8
- package/build/database/table-data/table-column.js +2 -0
- package/build/frontend-models/resource-definition.js +1 -138
- package/build/src/background-jobs/client.d.ts +30 -0
- package/build/src/background-jobs/client.d.ts.map +1 -1
- package/build/src/background-jobs/client.js +64 -4
- package/build/src/background-jobs/job.d.ts +19 -0
- package/build/src/background-jobs/job.d.ts.map +1 -1
- package/build/src/background-jobs/job.js +27 -1
- package/build/src/background-jobs/main.d.ts +41 -0
- package/build/src/background-jobs/main.d.ts.map +1 -1
- package/build/src/background-jobs/main.js +95 -14
- package/build/src/background-jobs/store.d.ts +136 -0
- package/build/src/background-jobs/store.d.ts.map +1 -1
- package/build/src/background-jobs/store.js +314 -42
- package/build/src/background-jobs/types.d.ts +86 -2
- package/build/src/background-jobs/types.d.ts.map +1 -1
- package/build/src/background-jobs/types.js +26 -2
- package/build/src/background-jobs/web/controller.d.ts.map +1 -1
- package/build/src/background-jobs/web/controller.js +2 -1
- package/build/src/database/advisory-lock-runner.d.ts +27 -14
- package/build/src/database/advisory-lock-runner.d.ts.map +1 -1
- package/build/src/database/advisory-lock-runner.js +27 -18
- package/build/src/database/drivers/mssql/index.d.ts +32 -0
- package/build/src/database/drivers/mssql/index.d.ts.map +1 -1
- package/build/src/database/drivers/mssql/index.js +86 -4
- package/build/src/database/record/index.d.ts +12 -8
- package/build/src/database/record/index.d.ts.map +1 -1
- package/build/src/database/record/index.js +11 -9
- package/build/src/database/table-data/table-column.d.ts.map +1 -1
- package/build/src/database/table-data/table-column.js +4 -1
- package/build/src/frontend-models/resource-definition.d.ts.map +1 -1
- package/build/src/frontend-models/resource-definition.js +2 -124
- package/build/src/sync/local-mutation-log.d.ts +7 -1
- package/build/src/sync/local-mutation-log.d.ts.map +1 -1
- package/build/src/sync/local-mutation-log.js +18 -7
- package/build/src/sync/peer-mutation-bundle.d.ts.map +1 -1
- package/build/src/sync/peer-mutation-bundle.js +9 -7
- package/build/src/sync/signed-sync-envelope-replay-service.d.ts.map +1 -1
- package/build/src/sync/signed-sync-envelope-replay-service.js +3 -1
- package/build/src/sync/sync-envelope-replay-service.d.ts +69 -0
- package/build/src/sync/sync-envelope-replay-service.d.ts.map +1 -1
- package/build/src/sync/sync-envelope-replay-service.js +186 -18
- package/build/src/testing/test-runner.d.ts.map +1 -1
- package/build/src/testing/test-runner.js +17 -22
- package/build/src/utils/sha256-hex.d.ts +10 -0
- package/build/src/utils/sha256-hex.d.ts.map +1 -0
- package/build/src/utils/sha256-hex.js +126 -0
- package/build/sync/local-mutation-log.js +19 -5
- package/build/sync/peer-mutation-bundle.js +8 -6
- package/build/sync/signed-sync-envelope-replay-service.js +2 -0
- package/build/sync/sync-envelope-replay-service.js +205 -17
- package/build/testing/test-runner.js +17 -22
- package/build/tsconfig.tsbuildinfo +1 -1
- package/build/utils/sha256-hex.js +141 -0
- package/package.json +1 -1
- package/src/background-jobs/client.js +71 -3
- package/src/background-jobs/job.js +30 -0
- package/src/background-jobs/main.js +100 -14
- package/src/background-jobs/store.js +344 -41
- package/src/background-jobs/types.js +25 -1
- package/src/background-jobs/web/controller.js +1 -0
- package/src/database/advisory-lock-runner.js +27 -17
- package/src/database/drivers/mssql/index.js +98 -3
- package/src/database/record/index.js +10 -8
- package/src/database/table-data/table-column.js +2 -0
- package/src/frontend-models/resource-definition.js +1 -138
- package/src/sync/local-mutation-log.js +19 -5
- package/src/sync/peer-mutation-bundle.js +8 -6
- package/src/sync/signed-sync-envelope-replay-service.js +2 -0
- package/src/sync/sync-envelope-replay-service.js +205 -17
- package/src/testing/test-runner.js +17 -22
- package/src/utils/sha256-hex.js +141 -0
|
@@ -52,7 +52,8 @@ class AdvisoryLockHoldTimeoutError extends Error {
|
|
|
52
52
|
|
|
53
53
|
/**
|
|
54
54
|
* Runs advisory locks on the caller connection by default, using a dedicated
|
|
55
|
-
* lock connection
|
|
55
|
+
* lock connection when `dedicatedConnection` is requested or when a positive
|
|
56
|
+
* hold timeout needs separate ownership.
|
|
56
57
|
*/
|
|
57
58
|
export default class AdvisoryLockRunner {
|
|
58
59
|
/**
|
|
@@ -67,17 +68,21 @@ export default class AdvisoryLockRunner {
|
|
|
67
68
|
|
|
68
69
|
/**
|
|
69
70
|
* Runs a callback after acquiring the advisory lock, waiting up to `timeoutMs`.
|
|
70
|
-
* When
|
|
71
|
-
*
|
|
72
|
-
*
|
|
71
|
+
* When `dedicatedConnection` is true the lock is acquired on a spawned
|
|
72
|
+
* connection that is released after the callback finishes, while the callback
|
|
73
|
+
* itself still runs against the caller/model connection. When a `holdTimeoutMs`
|
|
74
|
+
* is set the callback receives a `TimeoutControl` from awaitery for cooperative
|
|
75
|
+
* cancellation (`control.check()`, `control.signal`, `control.timedOut`,
|
|
76
|
+
* `control.remaining()`); a dedicated connection is also used so timeout
|
|
77
|
+
* cleanup can release the lock even if callback database work is stuck.
|
|
73
78
|
* @template T
|
|
74
79
|
* @param {string} name - Lock name.
|
|
75
80
|
* @param {(args?: {control: import("awaitery/build/timeout.js").TimeoutControl}) => Promise<T>} callback - Callback to invoke while the lock is held.
|
|
76
|
-
* @param {{timeoutMs?: number | null, holdTimeoutMs?: number | null}} [args] - Lock and hold timeout options.
|
|
81
|
+
* @param {{timeoutMs?: number | null, holdTimeoutMs?: number | null, dedicatedConnection?: boolean}} [args] - Lock and hold timeout options.
|
|
77
82
|
* @returns {Promise<T>} - Resolves with the callback result.
|
|
78
83
|
*/
|
|
79
84
|
async withAdvisoryLock(name, callback, args = {}) {
|
|
80
|
-
return await this.withLockConnection(args
|
|
85
|
+
return await this.withLockConnection(args, async (connection) => {
|
|
81
86
|
const acquired = await connection.acquireAdvisoryLock(name, args)
|
|
82
87
|
|
|
83
88
|
if (!acquired) {
|
|
@@ -90,16 +95,19 @@ export default class AdvisoryLockRunner {
|
|
|
90
95
|
|
|
91
96
|
/**
|
|
92
97
|
* Runs a callback only if the advisory lock can be acquired immediately.
|
|
93
|
-
* When
|
|
94
|
-
*
|
|
98
|
+
* When `dedicatedConnection` is true the lock is acquired on a spawned
|
|
99
|
+
* connection that is released after the callback finishes, while the callback
|
|
100
|
+
* itself still runs against the caller/model connection. When a `holdTimeoutMs`
|
|
101
|
+
* is set the callback receives a `TimeoutControl` from awaitery for cooperative
|
|
102
|
+
* cancellation.
|
|
95
103
|
* @template T
|
|
96
104
|
* @param {string} name - Lock name.
|
|
97
105
|
* @param {(args?: {control: import("awaitery/build/timeout.js").TimeoutControl}) => Promise<T>} callback - Callback to invoke while the lock is held.
|
|
98
|
-
* @param {{holdTimeoutMs?: number | null}} [args] - Hold timeout options.
|
|
106
|
+
* @param {{holdTimeoutMs?: number | null, dedicatedConnection?: boolean}} [args] - Hold timeout options.
|
|
99
107
|
* @returns {Promise<T>} - Resolves with the callback result.
|
|
100
108
|
*/
|
|
101
109
|
async withAdvisoryLockOrFail(name, callback, args = {}) {
|
|
102
|
-
return await this.withLockConnection(args
|
|
110
|
+
return await this.withLockConnection(args, async (connection) => {
|
|
103
111
|
const acquired = await connection.tryAcquireAdvisoryLock(name)
|
|
104
112
|
|
|
105
113
|
if (!acquired) {
|
|
@@ -125,15 +133,17 @@ export default class AdvisoryLockRunner {
|
|
|
125
133
|
}
|
|
126
134
|
|
|
127
135
|
/**
|
|
128
|
-
* Runs lock work on the caller connection unless
|
|
129
|
-
* its own lock connection.
|
|
136
|
+
* Runs lock work on the caller connection unless `dedicatedConnection` is
|
|
137
|
+
* requested or a positive hold timeout needs its own lock connection.
|
|
130
138
|
* @template T
|
|
131
|
-
* @param {number | null
|
|
139
|
+
* @param {{dedicatedConnection?: boolean, holdTimeoutMs?: number | null}} args - Lock connection options.
|
|
132
140
|
* @param {(connection: import("./drivers/base.js").default) => Promise<T>} callback - Callback receiving the connection that owns the advisory lock.
|
|
133
141
|
* @returns {Promise<T>} - Resolves with the callback result.
|
|
134
142
|
*/
|
|
135
|
-
async withLockConnection(
|
|
136
|
-
|
|
143
|
+
async withLockConnection(args, callback) {
|
|
144
|
+
const holdTimeoutMs = args.holdTimeoutMs
|
|
145
|
+
|
|
146
|
+
if (args.dedicatedConnection || (holdTimeoutMs && holdTimeoutMs > 0)) {
|
|
137
147
|
return await this.withDedicatedConnection(callback)
|
|
138
148
|
}
|
|
139
149
|
|
|
@@ -141,8 +151,8 @@ export default class AdvisoryLockRunner {
|
|
|
141
151
|
}
|
|
142
152
|
|
|
143
153
|
/**
|
|
144
|
-
* Spawns a
|
|
145
|
-
* the spawned driver owns the underlying physical connection.
|
|
154
|
+
* Spawns a dedicated lock connection and closes it after lock work completes
|
|
155
|
+
* when the spawned driver owns the underlying physical connection.
|
|
146
156
|
* @template T
|
|
147
157
|
* @param {(connection: import("./drivers/base.js").default) => Promise<T>} callback - Callback that receives the dedicated lock connection.
|
|
148
158
|
* @returns {Promise<T>} - Resolves with the callback result.
|
|
@@ -35,6 +35,9 @@ import UUID from "pure-uuid"
|
|
|
35
35
|
const APPLOCK_NOT_HELD_ERROR_NUMBER = 1223
|
|
36
36
|
|
|
37
37
|
export default class VelociousDatabaseDriversMssql extends Base{
|
|
38
|
+
/** @type {import("mssql").Transaction | null} */
|
|
39
|
+
_advisoryLockTransaction = null
|
|
40
|
+
|
|
38
41
|
async connect() {
|
|
39
42
|
const args = this.getArgs()
|
|
40
43
|
const sqlConfig = digg(args, "sqlConfig")
|
|
@@ -65,12 +68,22 @@ export default class VelociousDatabaseDriversMssql extends Base{
|
|
|
65
68
|
this.connection = undefined
|
|
66
69
|
this._currentTransaction = null
|
|
67
70
|
this._transactionsCount = 0
|
|
71
|
+
/** @type {Error | undefined} */
|
|
72
|
+
let sessionError
|
|
73
|
+
|
|
74
|
+
try {
|
|
75
|
+
await this._closeAdvisoryLockTransaction()
|
|
76
|
+
} catch (error) {
|
|
77
|
+
sessionError = error instanceof Error ? error : new Error("Failed to close MSSQL advisory-lock session", {cause: error})
|
|
78
|
+
}
|
|
68
79
|
|
|
69
80
|
try {
|
|
70
81
|
await timeout({timeout: 2000}, () => connection.close())
|
|
71
82
|
} catch (error) {
|
|
72
83
|
this.logger.warn("Failed to close MSSQL connection cleanly", {error})
|
|
73
84
|
}
|
|
85
|
+
|
|
86
|
+
if (sessionError) throw sessionError
|
|
74
87
|
}
|
|
75
88
|
|
|
76
89
|
/**
|
|
@@ -662,12 +675,15 @@ export default class VelociousDatabaseDriversMssql extends Base{
|
|
|
662
675
|
*/
|
|
663
676
|
async _acquireAdvisoryLock(name, {timeoutMs} = {}) {
|
|
664
677
|
const timeoutValue = typeof timeoutMs === "number" && timeoutMs >= 0 ? Math.ceil(timeoutMs) : -1
|
|
665
|
-
const rows = await this.
|
|
678
|
+
const rows = await this._advisoryLockQuery(
|
|
666
679
|
`DECLARE @velocious_advisory_lock_result INT; EXEC @velocious_advisory_lock_result = sp_getapplock @Resource = ${this.quote(name)}, @LockMode = 'Exclusive', @LockOwner = 'Session', @LockTimeout = ${timeoutValue}; SELECT @velocious_advisory_lock_result AS velocious_advisory_lock_result`
|
|
667
680
|
)
|
|
668
681
|
const result = Number(rows?.[0]?.velocious_advisory_lock_result)
|
|
669
682
|
|
|
670
683
|
if (result === 0 || result === 1) return true
|
|
684
|
+
|
|
685
|
+
await this._closeAdvisoryLockTransaction()
|
|
686
|
+
|
|
671
687
|
if (result === -1) return false
|
|
672
688
|
|
|
673
689
|
throw new Error(`sp_getapplock returned ${result} for advisory lock ${JSON.stringify(name)} (see SQL Server documentation for sp_getapplock return codes)`)
|
|
@@ -698,20 +714,99 @@ export default class VelociousDatabaseDriversMssql extends Base{
|
|
|
698
714
|
let rows
|
|
699
715
|
|
|
700
716
|
try {
|
|
701
|
-
rows = await this.
|
|
717
|
+
rows = await this._advisoryLockQuery(
|
|
702
718
|
`DECLARE @velocious_advisory_lock_result INT; EXEC @velocious_advisory_lock_result = sp_releaseapplock @Resource = ${this.quote(name)}, @LockOwner = 'Session'; SELECT @velocious_advisory_lock_result AS velocious_advisory_lock_result`
|
|
703
719
|
)
|
|
704
720
|
} catch (error) {
|
|
705
|
-
if (this._isApplockNotHeldError(error))
|
|
721
|
+
if (this._isApplockNotHeldError(error)) {
|
|
722
|
+
await this._closeAdvisoryLockTransactionIfFinalRelease()
|
|
723
|
+
|
|
724
|
+
return false
|
|
725
|
+
}
|
|
706
726
|
|
|
707
727
|
throw error
|
|
708
728
|
}
|
|
709
729
|
|
|
710
730
|
const result = Number(rows?.[0]?.velocious_advisory_lock_result)
|
|
711
731
|
|
|
732
|
+
await this._closeAdvisoryLockTransactionIfFinalRelease()
|
|
733
|
+
|
|
712
734
|
return result === 0
|
|
713
735
|
}
|
|
714
736
|
|
|
737
|
+
/**
|
|
738
|
+
* Runs an advisory-lock statement through one transaction request parent.
|
|
739
|
+
* node-mssql reserves one physical session for a Transaction, whereas
|
|
740
|
+
* separate ConnectionPool requests may check out different sessions. The
|
|
741
|
+
* transaction contains only application-lock statements; caller/model work
|
|
742
|
+
* continues through its original connection.
|
|
743
|
+
* @param {string} sql - Advisory-lock SQL.
|
|
744
|
+
* @returns {Promise<import("../base.js").QueryResultType>} - Result rows.
|
|
745
|
+
*/
|
|
746
|
+
async _advisoryLockQuery(sql) {
|
|
747
|
+
const transaction = await this._ensureAdvisoryLockTransaction()
|
|
748
|
+
|
|
749
|
+
try {
|
|
750
|
+
const request = new mssql.Request(transaction)
|
|
751
|
+
const result = await request.query(sql)
|
|
752
|
+
|
|
753
|
+
return Array.isArray(result.recordsets) ? result.recordsets[0] || [] : []
|
|
754
|
+
} catch (error) {
|
|
755
|
+
if (error instanceof Error) {
|
|
756
|
+
throw new Error(`Query failed '${error.message}': ${sql}`, {cause: error})
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
throw new Error(`Query failed '${error}': ${sql}`, {cause: error})
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
/**
|
|
764
|
+
* Starts the transaction request parent that reserves the advisory-lock
|
|
765
|
+
* session until the final release or driver close.
|
|
766
|
+
* @returns {Promise<import("mssql").Transaction>} - Session-affine parent.
|
|
767
|
+
*/
|
|
768
|
+
async _ensureAdvisoryLockTransaction() {
|
|
769
|
+
if (this._advisoryLockTransaction) return this._advisoryLockTransaction
|
|
770
|
+
if (!this.connection) await this.connect()
|
|
771
|
+
if (!this.connection) throw new Error("MSSQL connection unavailable for advisory lock")
|
|
772
|
+
|
|
773
|
+
const transaction = new mssql.Transaction(this.connection)
|
|
774
|
+
|
|
775
|
+
await transaction.begin()
|
|
776
|
+
this._advisoryLockTransaction = transaction
|
|
777
|
+
|
|
778
|
+
return transaction
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
/**
|
|
782
|
+
* Releases the reserved session after the last tracked lock release.
|
|
783
|
+
* Base untracks the current release after the driver hook returns, so a
|
|
784
|
+
* current total of one means this is the final release.
|
|
785
|
+
* @returns {Promise<void>} - Resolves after cleanup when this is final.
|
|
786
|
+
*/
|
|
787
|
+
async _closeAdvisoryLockTransactionIfFinalRelease() {
|
|
788
|
+
let heldCount = 0
|
|
789
|
+
|
|
790
|
+
for (const count of this._heldAdvisoryLocks.values()) heldCount += count
|
|
791
|
+
|
|
792
|
+
if (heldCount <= 1) await this._closeAdvisoryLockTransaction()
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
/**
|
|
796
|
+
* Rolls back the otherwise-empty transaction and returns its physical
|
|
797
|
+
* session to node-mssql. Rollback is cleanup only; advisory locks are
|
|
798
|
+
* explicitly released first whenever their release statement succeeds.
|
|
799
|
+
* @returns {Promise<void>} - Resolves after session cleanup.
|
|
800
|
+
*/
|
|
801
|
+
async _closeAdvisoryLockTransaction() {
|
|
802
|
+
const transaction = this._advisoryLockTransaction
|
|
803
|
+
|
|
804
|
+
if (!transaction) return
|
|
805
|
+
|
|
806
|
+
this._advisoryLockTransaction = null
|
|
807
|
+
await transaction.rollback()
|
|
808
|
+
}
|
|
809
|
+
|
|
715
810
|
/**
|
|
716
811
|
* Detects the SQL Server "application lock is not currently held" error
|
|
717
812
|
* raised by `sp_releaseapplock`. It walks the wrapped-error cause chain
|
|
@@ -2677,12 +2677,14 @@ class VelociousDatabaseRecord {
|
|
|
2677
2677
|
|
|
2678
2678
|
/**
|
|
2679
2679
|
* Runs the callback while holding a named advisory lock. Calls without
|
|
2680
|
-
*
|
|
2681
|
-
*
|
|
2682
|
-
*
|
|
2683
|
-
*
|
|
2684
|
-
*
|
|
2685
|
-
*
|
|
2680
|
+
* By default calls use the caller connection. Calls with `dedicatedConnection`
|
|
2681
|
+
* use a spawned lock connection that is released after the callback finishes,
|
|
2682
|
+
* while the callback itself still runs against the caller/model connection.
|
|
2683
|
+
* Calls with a positive `holdTimeoutMs` use a dedicated lock connection so
|
|
2684
|
+
* timeout cleanup can release the lock even when callback database work is
|
|
2685
|
+
* stuck. Advisory locks are cooperative and session-scoped: they serialize
|
|
2686
|
+
* callers that opt into the same `name`, without touching row or table locks,
|
|
2687
|
+
* so unrelated traffic is free to proceed.
|
|
2686
2688
|
*
|
|
2687
2689
|
* The lock is acquired before the callback runs and released in a
|
|
2688
2690
|
* `finally` block afterwards, so the callback's return value is
|
|
@@ -2690,7 +2692,7 @@ class VelociousDatabaseRecord {
|
|
|
2690
2692
|
* @template T
|
|
2691
2693
|
* @param {string} name - Lock name.
|
|
2692
2694
|
* @param {() => Promise<T>} callback - Callback to invoke while the lock is held.
|
|
2693
|
-
* @param {{timeoutMs?: number | null, holdTimeoutMs?: number | null}} [args] - `timeoutMs` caps how long we wait to acquire the lock; `holdTimeoutMs` caps how long the callback may hold it before the lock is released and `AdvisoryLockHoldTimeoutError` is thrown.
|
|
2695
|
+
* @param {{timeoutMs?: number | null, holdTimeoutMs?: number | null, dedicatedConnection?: boolean}} [args] - `timeoutMs` caps how long we wait to acquire the lock; `holdTimeoutMs` caps how long the callback may hold it before the lock is released and `AdvisoryLockHoldTimeoutError` is thrown; `dedicatedConnection` spawns a separate lock session without enabling a hold timeout.
|
|
2694
2696
|
* @returns {Promise<T>} - Resolves with the callback's return value.
|
|
2695
2697
|
* @throws {AdvisoryLockTimeoutError} - If `timeoutMs` elapses before the lock is granted.
|
|
2696
2698
|
* @throws {AdvisoryLockHoldTimeoutError} - If `holdTimeoutMs` elapses while the callback holds the lock.
|
|
@@ -2716,7 +2718,7 @@ class VelociousDatabaseRecord {
|
|
|
2716
2718
|
* @template T
|
|
2717
2719
|
* @param {string} name - Lock name.
|
|
2718
2720
|
* @param {() => Promise<T>} callback - Callback to invoke while the lock is held.
|
|
2719
|
-
* @param {{holdTimeoutMs?: number | null}} [args] - `holdTimeoutMs` caps how long the callback may hold the lock before it is released and `AdvisoryLockHoldTimeoutError` is thrown.
|
|
2721
|
+
* @param {{holdTimeoutMs?: number | null, dedicatedConnection?: boolean}} [args] - `holdTimeoutMs` caps how long the callback may hold the lock before it is released and `AdvisoryLockHoldTimeoutError` is thrown; `dedicatedConnection` spawns a separate lock session without enabling a hold timeout.
|
|
2720
2722
|
* @returns {Promise<T>} - Resolves with the callback's return value.
|
|
2721
2723
|
* @throws {AdvisoryLockBusyError} - If the lock is already held.
|
|
2722
2724
|
* @throws {AdvisoryLockHoldTimeoutError} - If `holdTimeoutMs` elapses while the callback holds the lock.
|
|
@@ -349,6 +349,8 @@ export default class TableColumn {
|
|
|
349
349
|
|
|
350
350
|
if (precision !== undefined && precision !== null) {
|
|
351
351
|
sql += scale !== undefined && scale !== null ? `(${precision}, ${scale})` : `(${precision})`
|
|
352
|
+
} else if (databaseType == "mysql" && type == "DATETIME") {
|
|
353
|
+
sql += "(3)"
|
|
352
354
|
} else if (type && maxlength !== undefined && maxlength !== null) {
|
|
353
355
|
sql += `(${maxlength})`
|
|
354
356
|
}
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import * as inflection from "inflection"
|
|
4
4
|
import FrontendModelBaseResource from "../frontend-model-resource/base-resource.js"
|
|
5
5
|
import restArgsError from "../utils/rest-args-error.js"
|
|
6
|
+
import sha256Hex from "../utils/sha256-hex.js"
|
|
6
7
|
import {validateFrontendModelResourceCommandName} from "./resource-config-validation.js"
|
|
7
8
|
|
|
8
9
|
/**
|
|
@@ -13,28 +14,6 @@ import {validateFrontendModelResourceCommandName} from "./resource-config-valida
|
|
|
13
14
|
* @property {import("../configuration-types.js").NormalizedFrontendModelResourceConfiguration} resourceConfiguration - Normalized resource configuration.
|
|
14
15
|
*/
|
|
15
16
|
const BASE_FRONTEND_MODEL_ABILITY_ACTIONS = ["create", "destroy", "read", "update"]
|
|
16
|
-
const SHA256_INITIAL_HASH = [
|
|
17
|
-
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
|
|
18
|
-
0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
|
|
19
|
-
]
|
|
20
|
-
const SHA256_K = [
|
|
21
|
-
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
|
|
22
|
-
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
|
|
23
|
-
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
|
|
24
|
-
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
|
|
25
|
-
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
|
|
26
|
-
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
|
27
|
-
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
|
|
28
|
-
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
|
|
29
|
-
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
|
|
30
|
-
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
|
|
31
|
-
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
|
|
32
|
-
0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
|
|
33
|
-
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
|
|
34
|
-
0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
|
|
35
|
-
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
|
|
36
|
-
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
|
|
37
|
-
]
|
|
38
17
|
const RESOURCE_STATIC_CONFIG_KEYS = new Set([
|
|
39
18
|
"abilities",
|
|
40
19
|
"attachments",
|
|
@@ -529,122 +508,6 @@ function syncPolicyHash(value) {
|
|
|
529
508
|
return `sha256-${sha256Hex(stableJsonStringify(value))}`
|
|
530
509
|
}
|
|
531
510
|
|
|
532
|
-
/**
|
|
533
|
-
* Computes SHA-256 without importing Node-only crypto modules, keeping this
|
|
534
|
-
* resource-definition module safe for Expo/browser bundles.
|
|
535
|
-
* @param {string} message - UTF-8 message.
|
|
536
|
-
* @returns {string} - Hex digest.
|
|
537
|
-
*/
|
|
538
|
-
function sha256Hex(message) {
|
|
539
|
-
const bytes = utf8Bytes(message)
|
|
540
|
-
const padded = [...bytes]
|
|
541
|
-
const bitLength = bytes.length * 8
|
|
542
|
-
const hash = [...SHA256_INITIAL_HASH]
|
|
543
|
-
/** @type {number[]} */
|
|
544
|
-
const words = new Array(64)
|
|
545
|
-
|
|
546
|
-
padded.push(0x80)
|
|
547
|
-
while (padded.length % 64 !== 56) padded.push(0)
|
|
548
|
-
|
|
549
|
-
const highLength = Math.floor(bitLength / 0x100000000)
|
|
550
|
-
const lowLength = bitLength >>> 0
|
|
551
|
-
|
|
552
|
-
for (const value of [highLength, lowLength]) {
|
|
553
|
-
padded.push((value >>> 24) & 0xff, (value >>> 16) & 0xff, (value >>> 8) & 0xff, value & 0xff)
|
|
554
|
-
}
|
|
555
|
-
|
|
556
|
-
for (let offset = 0; offset < padded.length; offset += 64) {
|
|
557
|
-
for (let i = 0; i < 16; i++) {
|
|
558
|
-
const index = offset + (i * 4)
|
|
559
|
-
|
|
560
|
-
words[i] = (((padded[index] || 0) << 24) | ((padded[index + 1] || 0) << 16) | ((padded[index + 2] || 0) << 8) | (padded[index + 3] || 0)) >>> 0
|
|
561
|
-
}
|
|
562
|
-
|
|
563
|
-
for (let i = 16; i < 64; i++) {
|
|
564
|
-
const s0 = rotateRight(words[i - 15], 7) ^ rotateRight(words[i - 15], 18) ^ (words[i - 15] >>> 3)
|
|
565
|
-
const s1 = rotateRight(words[i - 2], 17) ^ rotateRight(words[i - 2], 19) ^ (words[i - 2] >>> 10)
|
|
566
|
-
|
|
567
|
-
words[i] = add32(words[i - 16], s0, words[i - 7], s1)
|
|
568
|
-
}
|
|
569
|
-
|
|
570
|
-
let [a, b, c, d, e, f, g, h] = hash
|
|
571
|
-
|
|
572
|
-
for (let i = 0; i < 64; i++) {
|
|
573
|
-
const s1 = rotateRight(e, 6) ^ rotateRight(e, 11) ^ rotateRight(e, 25)
|
|
574
|
-
const ch = (e & f) ^ ((~e) & g)
|
|
575
|
-
const temp1 = add32(h, s1, ch, SHA256_K[i], words[i])
|
|
576
|
-
const s0 = rotateRight(a, 2) ^ rotateRight(a, 13) ^ rotateRight(a, 22)
|
|
577
|
-
const maj = (a & b) ^ (a & c) ^ (b & c)
|
|
578
|
-
const temp2 = add32(s0, maj)
|
|
579
|
-
|
|
580
|
-
h = g
|
|
581
|
-
g = f
|
|
582
|
-
f = e
|
|
583
|
-
e = add32(d, temp1)
|
|
584
|
-
d = c
|
|
585
|
-
c = b
|
|
586
|
-
b = a
|
|
587
|
-
a = add32(temp1, temp2)
|
|
588
|
-
}
|
|
589
|
-
|
|
590
|
-
hash[0] = add32(hash[0], a)
|
|
591
|
-
hash[1] = add32(hash[1], b)
|
|
592
|
-
hash[2] = add32(hash[2], c)
|
|
593
|
-
hash[3] = add32(hash[3], d)
|
|
594
|
-
hash[4] = add32(hash[4], e)
|
|
595
|
-
hash[5] = add32(hash[5], f)
|
|
596
|
-
hash[6] = add32(hash[6], g)
|
|
597
|
-
hash[7] = add32(hash[7], h)
|
|
598
|
-
}
|
|
599
|
-
|
|
600
|
-
return hash.map((value) => value.toString(16).padStart(8, "0")).join("")
|
|
601
|
-
}
|
|
602
|
-
|
|
603
|
-
/**
|
|
604
|
-
* Converts a string to UTF-8 bytes.
|
|
605
|
-
* @param {string} value - String value.
|
|
606
|
-
* @returns {number[]} - UTF-8 bytes.
|
|
607
|
-
*/
|
|
608
|
-
function utf8Bytes(value) {
|
|
609
|
-
/** @type {number[]} */
|
|
610
|
-
const bytes = []
|
|
611
|
-
|
|
612
|
-
for (const character of value) {
|
|
613
|
-
const codePoint = /** @type {number} */ (character.codePointAt(0))
|
|
614
|
-
|
|
615
|
-
if (codePoint <= 0x7f) {
|
|
616
|
-
bytes.push(codePoint)
|
|
617
|
-
} else if (codePoint <= 0x7ff) {
|
|
618
|
-
bytes.push(0xc0 | (codePoint >>> 6), 0x80 | (codePoint & 0x3f))
|
|
619
|
-
} else if (codePoint <= 0xffff) {
|
|
620
|
-
bytes.push(0xe0 | (codePoint >>> 12), 0x80 | ((codePoint >>> 6) & 0x3f), 0x80 | (codePoint & 0x3f))
|
|
621
|
-
} else {
|
|
622
|
-
bytes.push(0xf0 | (codePoint >>> 18), 0x80 | ((codePoint >>> 12) & 0x3f), 0x80 | ((codePoint >>> 6) & 0x3f), 0x80 | (codePoint & 0x3f))
|
|
623
|
-
}
|
|
624
|
-
}
|
|
625
|
-
|
|
626
|
-
return bytes
|
|
627
|
-
}
|
|
628
|
-
|
|
629
|
-
/**
|
|
630
|
-
* Adds unsigned 32-bit integers.
|
|
631
|
-
* @param {...number} values - Values to add.
|
|
632
|
-
* @returns {number} - Unsigned 32-bit result.
|
|
633
|
-
*/
|
|
634
|
-
function add32(...values) {
|
|
635
|
-
return values.reduce((sum, value) => (sum + value) >>> 0, 0)
|
|
636
|
-
}
|
|
637
|
-
|
|
638
|
-
/**
|
|
639
|
-
* Rotates a 32-bit integer right.
|
|
640
|
-
* @param {number} value - Value to rotate.
|
|
641
|
-
* @param {number} bits - Bit count.
|
|
642
|
-
* @returns {number} - Rotated value.
|
|
643
|
-
*/
|
|
644
|
-
function rotateRight(value, bits) {
|
|
645
|
-
return (value >>> bits) | (value << (32 - bits))
|
|
646
|
-
}
|
|
647
|
-
|
|
648
511
|
/**
|
|
649
512
|
* Validates that a sync config subtree is deterministic JSON and does not contain obvious secrets.
|
|
650
513
|
* @param {object} args - Arguments.
|
|
@@ -8,6 +8,11 @@ export default class BackgroundJobsClient {
|
|
|
8
8
|
configuration?: import("../configuration.js").default | undefined;
|
|
9
9
|
});
|
|
10
10
|
configurationPromise: Promise<import("../configuration.js").default>;
|
|
11
|
+
/**
|
|
12
|
+
* Builds a one-shot client socket request from the resolved configuration.
|
|
13
|
+
* @returns {Promise<BackgroundJobsSocketRequest>} - Socket request.
|
|
14
|
+
*/
|
|
15
|
+
_request(): Promise<BackgroundJobsSocketRequest>;
|
|
11
16
|
/**
|
|
12
17
|
* Runs enqueue.
|
|
13
18
|
* @param {object} args - Options.
|
|
@@ -21,5 +26,30 @@ export default class BackgroundJobsClient {
|
|
|
21
26
|
args: Array<unknown>;
|
|
22
27
|
options?: import("./types.js").BackgroundJobOptions | undefined;
|
|
23
28
|
}): Promise<string>;
|
|
29
|
+
/**
|
|
30
|
+
* Atomically replaces the queued owner of a stable schedule key.
|
|
31
|
+
* @param {object} args - Options.
|
|
32
|
+
* @param {string} args.scheduleKey - Stable logical schedule key.
|
|
33
|
+
* @param {string} args.jobName - Job name.
|
|
34
|
+
* @param {Array<?>} args.args - Job args.
|
|
35
|
+
* @param {import("./types.js").BackgroundJobOptions} [args.options] - Job options.
|
|
36
|
+
* @returns {Promise<import("./types.js").BackgroundJobReplacementResult>} - Replacement result.
|
|
37
|
+
*/
|
|
38
|
+
replaceScheduled({ scheduleKey, jobName, args, options }: {
|
|
39
|
+
scheduleKey: string;
|
|
40
|
+
jobName: string;
|
|
41
|
+
args: Array<unknown>;
|
|
42
|
+
options?: import("./types.js").BackgroundJobOptions | undefined;
|
|
43
|
+
}): Promise<import("./types.js").BackgroundJobReplacementResult>;
|
|
44
|
+
/**
|
|
45
|
+
* Cancels or detaches the current owner of a stable schedule key.
|
|
46
|
+
* @param {object} args - Options.
|
|
47
|
+
* @param {string} args.scheduleKey - Stable logical schedule key.
|
|
48
|
+
* @returns {Promise<import("./types.js").BackgroundJobCancellationResult>} - Cancellation result.
|
|
49
|
+
*/
|
|
50
|
+
cancelScheduled({ scheduleKey }: {
|
|
51
|
+
scheduleKey: string;
|
|
52
|
+
}): Promise<import("./types.js").BackgroundJobCancellationResult>;
|
|
24
53
|
}
|
|
54
|
+
import BackgroundJobsSocketRequest from "./socket-request.js";
|
|
25
55
|
//# sourceMappingURL=client.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/background-jobs/client.js"],"names":[],"mappings":"AAKA;IACE;;;;OAIG;IACH,gCAFG;QAAqD,aAAa;KACpE,EAGA;IADC,qEAAoG;IAGtG;;;;;;;OAOG;IACH,oCALG;QAAqB,OAAO,EAApB,MAAM;QACS,IAAI,EAAnB,KAAK,CAAC,OAAC,CAAC;QACyC,OAAO;KAChE,GAAU,OAAO,CAAC,MAAM,CAAC,
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/background-jobs/client.js"],"names":[],"mappings":"AAKA;IACE;;;;OAIG;IACH,gCAFG;QAAqD,aAAa;KACpE,EAGA;IADC,qEAAoG;IAGtG;;;OAGG;IACH,YAFa,OAAO,CAAC,2BAA2B,CAAC,CAOhD;IAED;;;;;;;OAOG;IACH,oCALG;QAAqB,OAAO,EAApB,MAAM;QACS,IAAI,EAAnB,KAAK,CAAC,OAAC,CAAC;QACyC,OAAO;KAChE,GAAU,OAAO,CAAC,MAAM,CAAC,CAyB3B;IAED;;;;;;;;OAQG;IACH,0DANG;QAAqB,WAAW,EAAxB,MAAM;QACO,OAAO,EAApB,MAAM;QACS,IAAI,EAAnB,KAAK,CAAC,OAAC,CAAC;QACyC,OAAO;KAChE,GAAU,OAAO,CAAC,OAAO,YAAY,EAAE,8BAA8B,CAAC,CAwBxE;IAED;;;;;OAKG;IACH,iCAHG;QAAqB,WAAW,EAAxB,MAAM;KACd,GAAU,OAAO,CAAC,OAAO,YAAY,EAAE,+BAA+B,CAAC,CAoBzE;CACF;wCAlHuC,qBAAqB"}
|
|
@@ -10,6 +10,15 @@ export default class BackgroundJobsClient {
|
|
|
10
10
|
constructor({ configuration } = {}) {
|
|
11
11
|
this.configurationPromise = configuration ? Promise.resolve(configuration) : configurationResolver();
|
|
12
12
|
}
|
|
13
|
+
/**
|
|
14
|
+
* Builds a one-shot client socket request from the resolved configuration.
|
|
15
|
+
* @returns {Promise<BackgroundJobsSocketRequest>} - Socket request.
|
|
16
|
+
*/
|
|
17
|
+
async _request() {
|
|
18
|
+
const configuration = await this.configurationPromise;
|
|
19
|
+
const { host, port } = configuration.getBackgroundJobsConfig();
|
|
20
|
+
return new BackgroundJobsSocketRequest({ host, port, role: "client" });
|
|
21
|
+
}
|
|
13
22
|
/**
|
|
14
23
|
* Runs enqueue.
|
|
15
24
|
* @param {object} args - Options.
|
|
@@ -19,9 +28,7 @@ export default class BackgroundJobsClient {
|
|
|
19
28
|
* @returns {Promise<string>} - Job id.
|
|
20
29
|
*/
|
|
21
30
|
async enqueue({ jobName, args, options }) {
|
|
22
|
-
const
|
|
23
|
-
const { host, port } = configuration.getBackgroundJobsConfig();
|
|
24
|
-
const request = new BackgroundJobsSocketRequest({ host, port, role: "client" });
|
|
31
|
+
const request = await this._request();
|
|
25
32
|
return await request.run({
|
|
26
33
|
onConnect: (jsonSocket) => {
|
|
27
34
|
jsonSocket.send({
|
|
@@ -42,5 +49,58 @@ export default class BackgroundJobsClient {
|
|
|
42
49
|
}
|
|
43
50
|
});
|
|
44
51
|
}
|
|
52
|
+
/**
|
|
53
|
+
* Atomically replaces the queued owner of a stable schedule key.
|
|
54
|
+
* @param {object} args - Options.
|
|
55
|
+
* @param {string} args.scheduleKey - Stable logical schedule key.
|
|
56
|
+
* @param {string} args.jobName - Job name.
|
|
57
|
+
* @param {Array<?>} args.args - Job args.
|
|
58
|
+
* @param {import("./types.js").BackgroundJobOptions} [args.options] - Job options.
|
|
59
|
+
* @returns {Promise<import("./types.js").BackgroundJobReplacementResult>} - Replacement result.
|
|
60
|
+
*/
|
|
61
|
+
async replaceScheduled({ scheduleKey, jobName, args, options }) {
|
|
62
|
+
const request = await this._request();
|
|
63
|
+
return await request.run({
|
|
64
|
+
onConnect: (jsonSocket) => {
|
|
65
|
+
jsonSocket.send({ type: "replace-scheduled", scheduleKey, jobName, args, options });
|
|
66
|
+
},
|
|
67
|
+
onMessage: ({ message, resolve, reject }) => {
|
|
68
|
+
if (message?.type === "schedule-replaced") {
|
|
69
|
+
resolve({
|
|
70
|
+
jobId: message.jobId,
|
|
71
|
+
previousJobId: message.previousJobId,
|
|
72
|
+
previousStatus: message.previousStatus
|
|
73
|
+
});
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
if (message?.type === "replace-scheduled-error") {
|
|
77
|
+
reject(new Error(message.error || "Failed to replace scheduled job"));
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Cancels or detaches the current owner of a stable schedule key.
|
|
84
|
+
* @param {object} args - Options.
|
|
85
|
+
* @param {string} args.scheduleKey - Stable logical schedule key.
|
|
86
|
+
* @returns {Promise<import("./types.js").BackgroundJobCancellationResult>} - Cancellation result.
|
|
87
|
+
*/
|
|
88
|
+
async cancelScheduled({ scheduleKey }) {
|
|
89
|
+
const request = await this._request();
|
|
90
|
+
return await request.run({
|
|
91
|
+
onConnect: (jsonSocket) => {
|
|
92
|
+
jsonSocket.send({ type: "cancel-scheduled", scheduleKey });
|
|
93
|
+
},
|
|
94
|
+
onMessage: ({ message, resolve, reject }) => {
|
|
95
|
+
if (message?.type === "schedule-cancelled") {
|
|
96
|
+
resolve({ jobId: message.jobId, outcome: message.outcome });
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
if (message?.type === "cancel-scheduled-error") {
|
|
100
|
+
reject(new Error(message.error || "Failed to cancel scheduled job"));
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
}
|
|
45
105
|
}
|
|
46
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
106
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xpZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2JhY2tncm91bmQtam9icy9jbGllbnQuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsWUFBWTtBQUVaLE9BQU8scUJBQXFCLE1BQU0sOEJBQThCLENBQUE7QUFDaEUsT0FBTywyQkFBMkIsTUFBTSxxQkFBcUIsQ0FBQTtBQUU3RCxNQUFNLENBQUMsT0FBTyxPQUFPLG9CQUFvQjtJQUN2Qzs7OztPQUlHO0lBQ0gsWUFBWSxFQUFDLGFBQWEsRUFBQyxHQUFHLEVBQUU7UUFDOUIsSUFBSSxDQUFDLG9CQUFvQixHQUFHLGFBQWEsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDLENBQUMscUJBQXFCLEVBQUUsQ0FBQTtJQUN0RyxDQUFDO0lBRUQ7OztPQUdHO0lBQ0gsS0FBSyxDQUFDLFFBQVE7UUFDWixNQUFNLGFBQWEsR0FBRyxNQUFNLElBQUksQ0FBQyxvQkFBb0IsQ0FBQTtRQUNyRCxNQUFNLEVBQUMsSUFBSSxFQUFFLElBQUksRUFBQyxHQUFHLGFBQWEsQ0FBQyx1QkFBdUIsRUFBRSxDQUFBO1FBRTVELE9BQU8sSUFBSSwyQkFBMkIsQ0FBQyxFQUFDLElBQUksRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBQyxDQUFDLENBQUE7SUFDdEUsQ0FBQztJQUVEOzs7Ozs7O09BT0c7SUFDSCxLQUFLLENBQUMsT0FBTyxDQUFDLEVBQUMsT0FBTyxFQUFFLElBQUksRUFBRSxPQUFPLEVBQUM7UUFDcEMsTUFBTSxPQUFPLEdBQUcsTUFBTSxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUE7UUFFckMsT0FBTyxNQUFNLE9BQU8sQ0FBQyxHQUFHLENBQUM7WUFDdkIsU0FBUyxFQUFFLENBQUMsVUFBVSxFQUFFLEVBQUU7Z0JBQ3hCLFVBQVUsQ0FBQyxJQUFJLENBQUM7b0JBQ2QsSUFBSSxFQUFFLFNBQVM7b0JBQ2Ys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QUMsQ0FBQTtJQUNKLENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbIi8vIEB0cy1jaGVja1xuXG5pbXBvcnQgY29uZmlndXJhdGlvblJlc29sdmVyIGZyb20gXCIuLi9jb25maWd1cmF0aW9uLXJlc29sdmVyLmpzXCJcbmltcG9ydCBCYWNrZ3JvdW5kSm9ic1NvY2tldFJlcXVlc3QgZnJvbSBcIi4vc29ja2V0LXJlcXVlc3QuanNcIlxuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBCYWNrZ3JvdW5kSm9ic0NsaWVudCB7XG4gIC8qKlxuICAgKiBSdW5zIGNvbnN0cnVjdG9yLlxuICAgKiBAcGFyYW0ge29iamVjdH0gW2FyZ3NdIC0gT3B0aW9ucy5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9jb25maWd1cmF0aW9uLmpzXCIpLmRlZmF1bHR9IFthcmdzLmNvbmZpZ3VyYXRpb25dIC0gQ29uZmlndXJhdGlvbi5cbiAgICovXG4gIGNvbnN0cnVjdG9yKHtjb25maWd1cmF0aW9ufSA9IHt9KSB7XG4gICAgdGhpcy5jb25maWd1cmF0aW9uUHJvbWlzZSA9IGNvbmZpZ3VyYXRpb24gPyBQcm9taXNlLnJlc29sdmUoY29uZmlndXJhdGlvbikgOiBjb25maWd1cmF0aW9uUmVzb2x2ZXIoKVxuICB9XG5cbiAgLyoqXG4gICAqIEJ1aWxkcyBhIG9uZS1zaG90IGNsaWVudCBzb2NrZXQgcmVxdWVzdCBmcm9tIHRoZSByZXNvbHZlZCBjb25maWd1cmF0aW9uLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxCYWNrZ3JvdW5kSm9ic1NvY2tldFJlcXVlc3Q+fSAtIFNvY2tldCByZXF1ZXN0LlxuICAgKi9cbiAgYXN5bmMgX3JlcXVlc3QoKSB7XG4gICAgY29uc3QgY29uZmlndXJhdGlvbiA9IGF3YWl0IHRoaXMuY29uZmlndXJhdGlvblByb21pc2VcbiAgICBjb25zdCB7aG9zdCwgcG9ydH0gPSBjb25maWd1cmF0aW9uLmdldEJhY2tncm91bmRKb2JzQ29uZmlnKClcblxuICAgIHJldHVybiBuZXcgQmFja2dyb3VuZEpvYnNTb2NrZXRSZXF1ZXN0KHtob3N0LCBwb3J0LCByb2xlOiBcImNsaWVudFwifSlcbiAgfVxuXG4gIC8qKlxuICAgKiBSdW5zIGVucXVldWUuXG4gICAqIEBwYXJhbSB7b2JqZWN0fSBhcmdzIC0gT3B0aW9ucy5cbiAgICogQHBhcmFtIHtzdHJpbmd9IGFyZ3Muam9iTmFtZSAtIEpvYiBuYW1lLlxuICAgKiBAcGFyYW0ge0FycmF5PD8+fSBhcmdzLmFyZ3MgLSBKb2IgYXJncy5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuL3R5cGVzLmpzXCIpLkJhY2tncm91bmRKb2JPcHRpb25zfSBbYXJncy5vcHRpb25zXSAtIEpvYiBvcHRpb25zLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxzdHJpbmc+fSAtIEpvYiBpZC5cbiAgICovXG4gIGFzeW5jIGVucXVldWUoe2pvYk5hbWUsIGFyZ3MsIG9wdGlvbnN9KSB7XG4gICAgY29uc3QgcmVxdWVzdCA9IGF3YWl0IHRoaXMuX3JlcXVlc3QoKVxuXG4gICAgcmV0dXJuIGF3YWl0IHJlcXVlc3QucnVuKHtcbiAgICAgIG9uQ29ubmVjdDogKGpzb25Tb2NrZXQpID0+IHtcbiAgICAgICAganNvblNvY2tldC5zZW5kKHtcbiAgICAgICAgICB0eXBlOiBcImVucXVldWVcIixcbiAgICAgICAgICBqb2JOYW1lLFxuICAgICAgICAgIGFyZ3MsXG4gICAgICAgICAgb3B0aW9uc1xuICAgICAgICB9KVxuICAgICAgfSxcbiAgICAgIG9uTWVzc2FnZTogKHttZXNzYWdlLCByZXNvbHZlLCByZWplY3R9KSA9PiB7XG4gICAgICAgIGlmIChtZXNzYWdlPy50eXBlID09PSBcImVucXVldWVkXCIpIHtcbiAgICAgICAgICByZXNvbHZlKG1lc3NhZ2Uuam9iSWQpXG4gICAgICAgICAgcmV0dXJuXG4gICAgICAgIH1cblxuICAgICAgICBpZiAobWVzc2FnZT8udHlwZSA9PT0gXCJlbnF1ZXVlLWVycm9yXCIpIHtcbiAgICAgICAgICByZWplY3QobmV3IEVycm9yKG1lc3NhZ2UuZXJyb3IgfHwgXCJGYWlsZWQgdG8gZW5xdWV1ZSBqb2JcIikpXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KVxuICB9XG5cbiAgLyoqXG4gICAqIEF0b21pY2FsbHkgcmVwbGFjZXMgdGhlIHF1ZXVlZCBvd25lciBvZiBhIHN0YWJsZSBzY2hlZHVsZSBrZXkuXG4gICAqIEBwYXJhbSB7b2JqZWN0fSBhcmdzIC0gT3B0aW9ucy5cbiAgICogQHBhcmFtIHtzdHJpbmd9IGFyZ3Muc2NoZWR1bGVLZXkgLSBTdGFibGUgbG9naWNhbCBzY2hlZHVsZSBrZXkuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBhcmdzLmpvYk5hbWUgLSBKb2IgbmFtZS5cbiAgICogQHBhcmFtIHtBcnJheTw/Pn0gYXJncy5hcmdzIC0gSm9iIGFyZ3MuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi90eXBlcy5qc1wiKS5CYWNrZ3JvdW5kSm9iT3B0aW9uc30gW2FyZ3Mub3B0aW9uc10gLSBKb2Igb3B0aW9ucy5cbiAgICogQHJldHVybnMge1Byb21pc2U8aW1wb3J0KFwiLi90eXBlcy5qc1wiKS5CYWNrZ3JvdW5kSm9iUmVwbGFjZW1lbnRSZXN1bHQ+fSAtIFJlcGxhY2VtZW50IHJlc3VsdC5cbiAgICovXG4gIGFzeW5jIHJlcGxhY2VTY2hlZHVsZWQoe3NjaGVkdWxlS2V5LCBqb2JOYW1lLCBhcmdzLCBvcHRpb25zfSkge1xuICAgIGNvbnN0IHJlcXVlc3QgPSBhd2FpdCB0aGlzLl9yZXF1ZXN0KClcblxuICAgIHJldHVybiBhd2FpdCByZXF1ZXN0LnJ1bih7XG4gICAgICBvbkNvbm5lY3Q6IChqc29uU29ja2V0KSA9PiB7XG4gICAgICAgIGpzb25Tb2NrZXQuc2VuZCh7dHlwZTogXCJyZXBsYWNlLXNjaGVkdWxlZFwiLCBzY2hlZHVsZUtleSwgam9iTmFtZSwgYXJncywgb3B0aW9uc30pXG4gICAgICB9LFxuICAgICAgb25NZXNzYWdlOiAoe21lc3NhZ2UsIHJlc29sdmUsIHJlamVjdH0pID0+IHtcbiAgICAgICAgaWYgKG1lc3NhZ2U/LnR5cGUgPT09IFwic2NoZWR1bGUtcmVwbGFjZWRcIikge1xuICAgICAgICAgIHJlc29sdmUoe1xuICAgICAgICAgICAgam9iSWQ6IG1lc3NhZ2Uuam9iSWQsXG4gICAgICAgICAgICBwcmV2aW91c0pvYklkOiBtZXNzYWdlLnByZXZpb3VzSm9iSWQsXG4gICAgICAgICAgICBwcmV2aW91c1N0YXR1czogbWVzc2FnZS5wcmV2aW91c1N0YXR1c1xuICAgICAgICAgIH0pXG4gICAgICAgICAgcmV0dXJuXG4gICAgICAgIH1cblxuICAgICAgICBpZiAobWVzc2FnZT8udHlwZSA9PT0gXCJyZXBsYWNlLXNjaGVkdWxlZC1lcnJvclwiKSB7XG4gICAgICAgICAgcmVqZWN0KG5ldyBFcnJvcihtZXNzYWdlLmVycm9yIHx8IFwiRmFpbGVkIHRvIHJlcGxhY2Ugc2NoZWR1bGVkIGpvYlwiKSlcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0pXG4gIH1cblxuICAvKipcbiAgICogQ2FuY2VscyBvciBkZXRhY2hlcyB0aGUgY3VycmVudCBvd25lciBvZiBhIHN0YWJsZSBzY2hlZHVsZSBrZXkuXG4gICAqIEBwYXJhbSB7b2JqZWN0fSBhcmdzIC0gT3B0aW9ucy5cbiAgICogQHBhcmFtIHtzdHJpbmd9IGFyZ3Muc2NoZWR1bGVLZXkgLSBTdGFibGUgbG9naWNhbCBzY2hlZHVsZSBrZXkuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPGltcG9ydChcIi4vdHlwZXMuanNcIikuQmFja2dyb3VuZEpvYkNhbmNlbGxhdGlvblJlc3VsdD59IC0gQ2FuY2VsbGF0aW9uIHJlc3VsdC5cbiAgICovXG4gIGFzeW5jIGNhbmNlbFNjaGVkdWxlZCh7c2NoZWR1bGVLZXl9KSB7XG4gICAgY29uc3QgcmVxdWVzdCA9IGF3YWl0IHRoaXMuX3JlcXVlc3QoKVxuXG4gICAgcmV0dXJuIGF3YWl0IHJlcXVlc3QucnVuKHtcbiAgICAgIG9uQ29ubmVjdDogKGpzb25Tb2NrZXQpID0+IHtcbiAgICAgICAganNvblNvY2tldC5zZW5kKHt0eXBlOiBcImNhbmNlbC1zY2hlZHVsZWRcIiwgc2NoZWR1bGVLZXl9KVxuICAgICAgfSxcbiAgICAgIG9uTWVzc2FnZTogKHttZXNzYWdlLCByZXNvbHZlLCByZWplY3R9KSA9PiB7XG4gICAgICAgIGlmIChtZXNzYWdlPy50eXBlID09PSBcInNjaGVkdWxlLWNhbmNlbGxlZFwiKSB7XG4gICAgICAgICAgcmVzb2x2ZSh7am9iSWQ6IG1lc3NhZ2Uuam9iSWQsIG91dGNvbWU6IG1lc3NhZ2Uub3V0Y29tZX0pXG4gICAgICAgICAgcmV0dXJuXG4gICAgICAgIH1cblxuICAgICAgICBpZiAobWVzc2FnZT8udHlwZSA9PT0gXCJjYW5jZWwtc2NoZWR1bGVkLWVycm9yXCIpIHtcbiAgICAgICAgICByZWplY3QobmV3IEVycm9yKG1lc3NhZ2UuZXJyb3IgfHwgXCJGYWlsZWQgdG8gY2FuY2VsIHNjaGVkdWxlZCBqb2JcIikpXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KVxuICB9XG59XG4iXX0=
|
|
@@ -65,6 +65,25 @@ export default class VelociousJob<TArgs extends Array<unknown> = []> {
|
|
|
65
65
|
args: Array<unknown>;
|
|
66
66
|
options?: import("./types.js").BackgroundJobOptions | undefined;
|
|
67
67
|
}): Promise<string>;
|
|
68
|
+
/**
|
|
69
|
+
* Atomically replaces this job class's queued owner for a stable schedule key.
|
|
70
|
+
* @param {object} args - Options.
|
|
71
|
+
* @param {string} args.scheduleKey - Stable logical schedule key.
|
|
72
|
+
* @param {Array<?>} args.args - Job args.
|
|
73
|
+
* @param {import("./types.js").BackgroundJobOptions} [args.options] - Job options.
|
|
74
|
+
* @returns {Promise<import("./types.js").BackgroundJobReplacementResult>} - Replacement result.
|
|
75
|
+
*/
|
|
76
|
+
static replaceScheduled({ scheduleKey, args, options }: {
|
|
77
|
+
scheduleKey: string;
|
|
78
|
+
args: Array<unknown>;
|
|
79
|
+
options?: import("./types.js").BackgroundJobOptions | undefined;
|
|
80
|
+
}): Promise<import("./types.js").BackgroundJobReplacementResult>;
|
|
81
|
+
/**
|
|
82
|
+
* Cancels or detaches the current owner of a stable schedule key.
|
|
83
|
+
* @param {string} scheduleKey - Stable logical schedule key.
|
|
84
|
+
* @returns {Promise<import("./types.js").BackgroundJobCancellationResult>} - Cancellation result.
|
|
85
|
+
*/
|
|
86
|
+
static cancelScheduled(scheduleKey: string): Promise<import("./types.js").BackgroundJobCancellationResult>;
|
|
68
87
|
/**
|
|
69
88
|
* Runs split args and options.
|
|
70
89
|
* @param {Array<?>} args - Job args.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"job.d.ts","sourceRoot":"","sources":["../../../src/background-jobs/job.js"],"names":[],"mappings":"AAIA;;;;;;;;;GASG;AACH,kCAFyB,KAAK,SAAhB,KAAK,CAAC,OAAC,CAAE;IAGrB;;;;;;OAMG;IACH,4BAFU,MAAM,EAAE,GAAG,SAAS,CAEQ;IAEtC;;;;;;OAMG;IACH,cAFU,MAAM,GAAG,SAAS,CAEJ;IAExB;;;;;;;;;OASG;IACH,qBAFU,MAAM,GAAG,SAAS,CAEG;IAE/B;;;OAGG;IACH,kBAFa,MAAM,CAIlB;IAED;;;;;OAKG;IACH,2BAHW,OAAO,YAAY,EAAE,oBAAoB,GAAG,SAAS,GACnD,OAAO,YAAY,EAAE,oBAAoB,CAUrD;IAED;;;;OAIG;IACH,6BAHc,OAAC,EAAA,GACF,OAAO,CAAC,MAAM,CAAC,CAW3B;IAED;;;;;;OAMG;IACH,kDAJG;QAAuB,IAAI,EAAnB,KAAK,CAAC,OAAC,CAAC;QACyC,OAAO;KAChE,GAAU,OAAO,CAAC,MAAM,CAAC,CAU3B;IAED;;;;OAIG;IACH,kCAHW,KAAK,CAAC,OAAC,CAAC,GACN;QAAC,OAAO,EAAE,KAAK,CAAC,OAAC,CAAC,CAAC;QAAC,UAAU,EAAE,OAAO,YAAY,EAAE,oBAAoB,CAAA;KAAC,CAgBtF;IAED;;;;OAIG;IACH,kBAHW,KAAK,GACH,OAAO,CAAC,IAAI,CAAC,CAIzB;CACF"}
|
|
1
|
+
{"version":3,"file":"job.d.ts","sourceRoot":"","sources":["../../../src/background-jobs/job.js"],"names":[],"mappings":"AAIA;;;;;;;;;GASG;AACH,kCAFyB,KAAK,SAAhB,KAAK,CAAC,OAAC,CAAE;IAGrB;;;;;;OAMG;IACH,4BAFU,MAAM,EAAE,GAAG,SAAS,CAEQ;IAEtC;;;;;;OAMG;IACH,cAFU,MAAM,GAAG,SAAS,CAEJ;IAExB;;;;;;;;;OASG;IACH,qBAFU,MAAM,GAAG,SAAS,CAEG;IAE/B;;;OAGG;IACH,kBAFa,MAAM,CAIlB;IAED;;;;;OAKG;IACH,2BAHW,OAAO,YAAY,EAAE,oBAAoB,GAAG,SAAS,GACnD,OAAO,YAAY,EAAE,oBAAoB,CAUrD;IAED;;;;OAIG;IACH,6BAHc,OAAC,EAAA,GACF,OAAO,CAAC,MAAM,CAAC,CAW3B;IAED;;;;;;OAMG;IACH,kDAJG;QAAuB,IAAI,EAAnB,KAAK,CAAC,OAAC,CAAC;QACyC,OAAO;KAChE,GAAU,OAAO,CAAC,MAAM,CAAC,CAU3B;IAED;;;;;;;OAOG;IACH,wDALG;QAAqB,WAAW,EAAxB,MAAM;QACS,IAAI,EAAnB,KAAK,CAAC,OAAC,CAAC;QACyC,OAAO;KAChE,GAAU,OAAO,CAAC,OAAO,YAAY,EAAE,8BAA8B,CAAC,CAWxE;IAED;;;;OAIG;IACH,oCAHW,MAAM,GACJ,OAAO,CAAC,OAAO,YAAY,EAAE,+BAA+B,CAAC,CAMzE;IAED;;;;OAIG;IACH,kCAHW,KAAK,CAAC,OAAC,CAAC,GACN;QAAC,OAAO,EAAE,KAAK,CAAC,OAAC,CAAC,CAAC;QAAC,UAAU,EAAE,OAAO,YAAY,EAAE,oBAAoB,CAAA;KAAC,CAgBtF;IAED;;;;OAIG;IACH,kBAHW,KAAK,GACH,OAAO,CAAC,IAAI,CAAC,CAIzB;CACF"}
|