@indigoai-us/hq-cli 5.345.35 → 5.345.36
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/CHANGELOG.md +4 -0
- package/dist/commands/cloud.js +6 -5
- package/dist/hq-cloud-sync-runner/bin/sync-runner.js +7226 -4092
- package/dist/hq-cloud-sync-runner/package.json +1 -1
- package/dist/lib/flag-registry-worker-source.generated.d.ts +1 -1
- package/dist/lib/flag-registry-worker-source.generated.js +1 -1
- package/dist/utils/package-use-lease.d.ts +17 -0
- package/dist/utils/package-use-lease.js +36 -0
- package/dist/utils/sync-operation-lock.d.ts +37 -0
- package/dist/utils/sync-operation-lock.js +40 -0
- package/package.json +2 -2
|
@@ -50,5 +50,22 @@ export declare const __test__: {
|
|
|
50
50
|
waitForUpdateRequest: typeof waitForUpdateRequest;
|
|
51
51
|
setCurrentPackageUseLease(lease: PackageUseLease | null): void;
|
|
52
52
|
};
|
|
53
|
+
/**
|
|
54
|
+
* Run `wait` with this process's package-use lease DROPPED, then reacquire the
|
|
55
|
+
* lease before returning.
|
|
56
|
+
*
|
|
57
|
+
* `hq sync` runs under purpose `"command"`, and
|
|
58
|
+
* {@link releasePackageUseLeaseAfterCommandLoad} deliberately keeps that lease
|
|
59
|
+
* for the whole command. hq-cloud's per-root operation lock then waits — by
|
|
60
|
+
* default without a bound — for whichever process is already syncing, so an old
|
|
61
|
+
* `hq` install pinned `hq pkg update` for the entire length of somebody else's
|
|
62
|
+
* lock wait (HQ-DESKTOP-8H). Queuing is not using the package: drop the lease
|
|
63
|
+
* while this process is only waiting, and take it again once the wait is over.
|
|
64
|
+
*
|
|
65
|
+
* A reacquire that throws {@link PackageUseUpdatePendingError} is the correct
|
|
66
|
+
* outcome — an update landed while we queued — and propagates to the caller. On
|
|
67
|
+
* the failure path the original error wins and the reacquire is best-effort.
|
|
68
|
+
*/
|
|
69
|
+
export declare function withPackageUseLeaseReleasedDuring<T>(wait: () => Promise<T>, argv?: readonly string[], release?: () => void, reacquire?: (argv: readonly string[]) => unknown): Promise<T>;
|
|
53
70
|
export {};
|
|
54
71
|
//# sourceMappingURL=package-use-lease.d.ts.map
|
|
@@ -413,4 +413,40 @@ export const __test__ = {
|
|
|
413
413
|
currentPackageUseLease = lease;
|
|
414
414
|
},
|
|
415
415
|
};
|
|
416
|
+
/**
|
|
417
|
+
* Run `wait` with this process's package-use lease DROPPED, then reacquire the
|
|
418
|
+
* lease before returning.
|
|
419
|
+
*
|
|
420
|
+
* `hq sync` runs under purpose `"command"`, and
|
|
421
|
+
* {@link releasePackageUseLeaseAfterCommandLoad} deliberately keeps that lease
|
|
422
|
+
* for the whole command. hq-cloud's per-root operation lock then waits — by
|
|
423
|
+
* default without a bound — for whichever process is already syncing, so an old
|
|
424
|
+
* `hq` install pinned `hq pkg update` for the entire length of somebody else's
|
|
425
|
+
* lock wait (HQ-DESKTOP-8H). Queuing is not using the package: drop the lease
|
|
426
|
+
* while this process is only waiting, and take it again once the wait is over.
|
|
427
|
+
*
|
|
428
|
+
* A reacquire that throws {@link PackageUseUpdatePendingError} is the correct
|
|
429
|
+
* outcome — an update landed while we queued — and propagates to the caller. On
|
|
430
|
+
* the failure path the original error wins and the reacquire is best-effort.
|
|
431
|
+
*/
|
|
432
|
+
export async function withPackageUseLeaseReleasedDuring(wait, argv = process.argv, release = releaseCurrentPackageUseLease, reacquire = acquireCurrentPackageUseLease) {
|
|
433
|
+
if (currentPackageUseLease === null)
|
|
434
|
+
return wait();
|
|
435
|
+
release();
|
|
436
|
+
let result;
|
|
437
|
+
try {
|
|
438
|
+
result = await wait();
|
|
439
|
+
}
|
|
440
|
+
catch (error) {
|
|
441
|
+
try {
|
|
442
|
+
reacquire(argv);
|
|
443
|
+
}
|
|
444
|
+
catch {
|
|
445
|
+
// The caller's error is the one worth reporting.
|
|
446
|
+
}
|
|
447
|
+
throw error;
|
|
448
|
+
}
|
|
449
|
+
reacquire(argv);
|
|
450
|
+
return result;
|
|
451
|
+
}
|
|
416
452
|
//# sourceMappingURL=package-use-lease.js.map
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Take hq-cloud's per-root operation lock for a sync pass from hq-cli, so the
|
|
3
|
+
* wait for an existing holder happens OUTSIDE this process's package-use lease.
|
|
4
|
+
*
|
|
5
|
+
* `sync()` normally wraps itself in `withOperationLock`, which waits for a live
|
|
6
|
+
* holder with no bound unless `HQ_OP_LOCK_TIMEOUT` says otherwise. `hq sync`
|
|
7
|
+
* runs under package-use purpose `"command"`, whose lease is held for the whole
|
|
8
|
+
* command, so the queued process pinned the installed `hq` version — and
|
|
9
|
+
* therefore blocked `hq pkg update` — for the entire length of somebody else's
|
|
10
|
+
* sync (HQ-DESKTOP-8H).
|
|
11
|
+
*
|
|
12
|
+
* Acquiring the lock here instead lets the lease be dropped across the wait and
|
|
13
|
+
* retaken the moment the lock is held, before any sync work runs.
|
|
14
|
+
* `operationLockAlreadyHeld` is the seam hq-cloud exposes for a caller that owns
|
|
15
|
+
* the lock; the lock is NOT reentrant in-process, so the flag is required rather
|
|
16
|
+
* than optional.
|
|
17
|
+
*/
|
|
18
|
+
import { type SyncOptions, type SyncResult } from "@indigoai-us/hq-cloud";
|
|
19
|
+
import { type LockHandle } from "@indigoai-us/hq-cloud/operation-lock";
|
|
20
|
+
export interface SyncUnderOperationLockDeps<Options, Result> {
|
|
21
|
+
sync: (options: Options & {
|
|
22
|
+
operationLockAlreadyHeld: true;
|
|
23
|
+
}) => Promise<Result>;
|
|
24
|
+
/** Injected in tests; defaults to hq-cloud's wait-capable acquisition. */
|
|
25
|
+
acquireLock?: (hqRoot: string) => Promise<LockHandle>;
|
|
26
|
+
/** Injected in tests; defaults to the real lease drop/retake. */
|
|
27
|
+
withLeaseReleased?: <T>(wait: () => Promise<T>) => Promise<T>;
|
|
28
|
+
}
|
|
29
|
+
export declare function syncUnderOperationLock<Options extends {
|
|
30
|
+
hqRoot: string;
|
|
31
|
+
}, Result>(options: Options, deps: SyncUnderOperationLockDeps<Options, Result>): Promise<Result>;
|
|
32
|
+
/**
|
|
33
|
+
* The production sync leg: hq-cloud's `sync()` under a lock this process takes
|
|
34
|
+
* itself. Every `hq sync` path in `src/commands/cloud.ts` calls this.
|
|
35
|
+
*/
|
|
36
|
+
export declare function syncLeg(options: SyncOptions): Promise<SyncResult>;
|
|
37
|
+
//# sourceMappingURL=sync-operation-lock.d.ts.map
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Take hq-cloud's per-root operation lock for a sync pass from hq-cli, so the
|
|
3
|
+
* wait for an existing holder happens OUTSIDE this process's package-use lease.
|
|
4
|
+
*
|
|
5
|
+
* `sync()` normally wraps itself in `withOperationLock`, which waits for a live
|
|
6
|
+
* holder with no bound unless `HQ_OP_LOCK_TIMEOUT` says otherwise. `hq sync`
|
|
7
|
+
* runs under package-use purpose `"command"`, whose lease is held for the whole
|
|
8
|
+
* command, so the queued process pinned the installed `hq` version — and
|
|
9
|
+
* therefore blocked `hq pkg update` — for the entire length of somebody else's
|
|
10
|
+
* sync (HQ-DESKTOP-8H).
|
|
11
|
+
*
|
|
12
|
+
* Acquiring the lock here instead lets the lease be dropped across the wait and
|
|
13
|
+
* retaken the moment the lock is held, before any sync work runs.
|
|
14
|
+
* `operationLockAlreadyHeld` is the seam hq-cloud exposes for a caller that owns
|
|
15
|
+
* the lock; the lock is NOT reentrant in-process, so the flag is required rather
|
|
16
|
+
* than optional.
|
|
17
|
+
*/
|
|
18
|
+
import { sync } from "@indigoai-us/hq-cloud";
|
|
19
|
+
import { acquireOperationLockAsync, } from "@indigoai-us/hq-cloud/operation-lock";
|
|
20
|
+
import { withPackageUseLeaseReleasedDuring } from "./package-use-lease.js";
|
|
21
|
+
export async function syncUnderOperationLock(options, deps) {
|
|
22
|
+
const acquireLock = deps.acquireLock ?? ((hqRoot) => acquireOperationLockAsync(hqRoot, "sync"));
|
|
23
|
+
const withLeaseReleased = deps.withLeaseReleased ??
|
|
24
|
+
((wait) => withPackageUseLeaseReleasedDuring(wait));
|
|
25
|
+
const handle = await withLeaseReleased(() => acquireLock(options.hqRoot));
|
|
26
|
+
try {
|
|
27
|
+
return await deps.sync({ ...options, operationLockAlreadyHeld: true });
|
|
28
|
+
}
|
|
29
|
+
finally {
|
|
30
|
+
handle.release();
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* The production sync leg: hq-cloud's `sync()` under a lock this process takes
|
|
35
|
+
* itself. Every `hq sync` path in `src/commands/cloud.ts` calls this.
|
|
36
|
+
*/
|
|
37
|
+
export function syncLeg(options) {
|
|
38
|
+
return syncUnderOperationLock(options, { sync });
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=sync-operation-lock.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@indigoai-us/hq-cli",
|
|
3
|
-
"version": "5.345.
|
|
3
|
+
"version": "5.345.36",
|
|
4
4
|
"description": "HQ by Indigo management CLI — modules and cloud sync",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
"@aws-sdk/client-iot-data-plane": "^3.1096.0",
|
|
49
49
|
"@aws-sdk/client-s3": "^3.1049.0",
|
|
50
50
|
"@aws-sdk/dsql-signer": "^3.1146.0",
|
|
51
|
-
"@indigoai-us/hq-cloud": "~6.18.
|
|
51
|
+
"@indigoai-us/hq-cloud": "~6.18.50",
|
|
52
52
|
"@indigoai-us/hq-flags-client": "^0.1.2",
|
|
53
53
|
"@modelcontextprotocol/sdk": "1.29.0",
|
|
54
54
|
"@sentry/node": "^10.49.0",
|