Skip to content

Refactor package build lifecycle and improve resource management#71

Merged
miccy merged 91 commits intomainfrom
dev/astro-6-upgrade
Mar 17, 2026
Merged

Refactor package build lifecycle and improve resource management#71
miccy merged 91 commits intomainfrom
dev/astro-6-upgrade

Conversation

@miccy
Copy link
Contributor

@miccy miccy commented Mar 17, 2026

Summary by CodeRabbit

Poznámky k vydání

  • Nové funkce

    • Přidána kolekce StructuralMap pro správu registrů a tabulek s imutabilními klíči
    • Veřejný export polyfillů pro zlepšenou kompatibilitu
  • Vylepšení

    • Zpřesnění správy životního cyklu asynchronních prostředků
    • Vylepšená infrastruktura pro zpracování chyb
  • Chores

    • Aktualizovány závislosti napříč projekty

steida added 30 commits March 1, 2026 22:42
Replaced prepack with prepare in publishable package manifests so build runs in git-based installs and standard packaging flows. This keeps direct GitHub package installs working while avoiding reliance on prepack-only behavior.
Added a root TypeScript solution config for package references and a root typecheck script that runs tsc build mode with noEmit. Also updated verify to run typecheck first so type errors in package tests are caught consistently across the monorepo.
Replace redundant double-step TypeScript builds ("tsc --build --clean && tsc --build") with a single "tsc --build" invocation across packages (common, nodejs, react-native, react-web, react, svelte, vue, web, apps/relay). Update svelte build to remove the extra tsc pass. Add a root script "clean:ts" (tsc --build --clean tsconfig.typecheck.json) and run it before the monorepo build by prepending it to the root "build" script.
Remove runtime dependency on disposablestack and implement an owned DisposableStack/AsyncDisposableStack polyfill in packages/common/src/Polyfills.ts. The polyfill installs Symbol.dispose / Symbol.asyncDispose and SuppressedError, includes a WebKit completion-bug fix (es-shims/DisposableStack#9), and exposes behavior-parity with Node where needed. Add comprehensive conformance tests in packages/common/test/Polyfills.test.ts (ports upstream es-shims/test262 checks and adds Evolu-specific regressions). Also update package.json to drop the disposablestack dependency and adjust browser test setup.
Introduce keyed concurrency registries and refactor instance lifecycle handling: add createSemaphoreByKey/createMutexByKey and extend Semaphore with withPermits and snapshot for weighted/FIFO semantics; move TaskInstances into Task.ts and implement a Task-based instances registry using mutexes per key. Refactor Instances disposal to use DisposableStack (LIFO) and adapt Resources, Relay and Shared to use the new keyed mutex API. Improve Task docs and yield/timeout fallbacks, and update tests to cover semaphore snapshots, weighted permits, scheduler fallbacks, and the revised disposal error representation.

Commit before further refactor. Fixes memory leak in Relay (Instances with Mutexes was a stupid design).
Refactor the evolu ESLint rule to recursively detect CallExpression and NewExpression nodes inside exported const initializers (not just top-level calls). The rule now traverses node children via sourceCode.visitorKeys, skips function boundaries and IIFEs, treats arrow/function expressions as non-pure callee cases, and inserts /*#__PURE__*/ annotations where missing. Updated rule messages/descriptions accordingly and added comprehensive tests (scripts/eslint-plugin-evolu.test.mts) covering top-level, nested calls, new expressions, function bodies, and IIFEs. Also disabled jsdoc/check-alignment in eslint.config.mjs with a TODO about Copilot inserting extra spaces.
Large refactor to clarify Run/Task/Fiber concepts and rename concurrency helpers. Key changes: replace FiberState/FiberSnapshot with RunState/RunSnapshot and rename related types/events; introduce Run.create and adjust daemon semantics; replace runClosing* with runStopped* errors/abort reasons. Add AbortMask/Concurrency types earlier, and rename parallel->concurrently (plus updated callers). Remove TaskInstances/createTaskInstances and createDeferreds APIs and add MutexRef/createMutexRef + createMutex utilities (with snapshot support). Various doc and capitalization fixes to use consistent "Run"/"Task"/"Fiber" terminology and adjust microtask/abort semantics.
Replace the previous createTaskInstances approach with an explicit Map plus a per-name mutex (createMutexByKey) to avoid races when creating SharedEvolu instances. SharedEvolu instances are now stored in sharedEvolusByName and created under sharedEvolusMutexByName.withLock; deletion on dispose is also performed under the same lock. Refactor createSharedEvolu to derive a child console from run.deps, extract addPorts into a standalone function, and make message switch defaults use exhaustiveCheck. Misc: adjust imports (remove Console type, add exhaustiveCheck and createMutexByKey) and tidy message handling and lifecycle logic.
Merged the Evolu SQLite JSON helpers into Query.ts, removed the root kysely namespace export, and exposed the helpers as explicit named exports.

Also fixed recursive parsing of nested Evolu-marked JSON payloads, updated tests to cover the merged helper implementation, and refreshed docs, playgrounds, examples, and the changeset for the new API.
Simplify createSqlite by replacing manual result handling with run.orThrow when creating the Sqlite driver. This removes the intermediate result variable and explicit ok check, directly assigning the driver and letting run.orThrow propagate errors.
Update documentation across Result.ts and Task.ts to clarify when to wrap thrown errors in Result (use trySync/tryAsync for recoverable, actionable errors) versus letting unrecoverable errors propagate to a global handler. Add guidance to prefer platform-specific createRun adapters (e.g. @evolu/web, @evolu/nodejs, @evolu/react-native) for global error handling. Remove the unused UnknownError import and the large example surrounding it, and drop a stray comment about Promise.try. Small cleanup focused on docs and imports — no behavioral changes to runtime logic.
Document preferred imperative style for composing sequential Tasks (using await/run) to avoid pipe/chain API duplication. Update AsyncDisposableStack.use signature to return PromiseLike<Result<T, E | AbortError>> to reflect abort semantics, and adjust the test to assert the resulting type is Result<Resource, AbortError>.
@miccy miccy self-assigned this Mar 17, 2026
@miccy miccy added upstream Needs cherry-pick or merge from upstream fix Repair any bug update Update libs and deps labels Mar 17, 2026
Copilot AI review requested due to automatic review settings March 17, 2026 09:00
@miccy miccy marked this pull request as ready for review March 17, 2026 09:00
@miccy miccy requested a review from a team as a code owner March 17, 2026 09:00
@miccy miccy merged commit b13c409 into main Mar 17, 2026
5 of 36 checks passed
@miccy miccy deleted the dev/astro-6-upgrade branch March 17, 2026 09:00
@coderabbitai
Copy link

coderabbitai bot commented Mar 17, 2026

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 773943f6-488b-4844-b680-afa41a44e11d

📥 Commits

Reviewing files that changed from the base of the PR and between c19eaba and 042f041.

⛔ Files ignored due to path filters (1)
  • bun.lock is excluded by !**/*.lock
📒 Files selected for processing (79)
  • .changeset/structural-map-uint8array.md
  • .github/copilot-instructions.md
  • .github/workflows/ci.yaml
  • .github/workflows/ws-browser-nightly.yaml
  • .gitignore
  • apps/relay/package.json
  • apps/relay/src/index.ts
  • apps/relay/src/startBunRelay.ts
  • biome.json
  • examples/angular-vite-pwa/package.json
  • examples/astro/package.json
  • examples/react-electron/package.json
  • examples/react-expo/package.json
  • examples/react-nextjs/package.json
  • examples/react-vite-pwa/package.json
  • examples/svelte-vite-pwa/package.json
  • examples/tanstack-start/package.json
  • examples/tauri/package.json
  • examples/vue-vite-pwa/package.json
  • package.json
  • packages/common/package.json
  • packages/common/src/Assert.ts
  • packages/common/src/Function.ts
  • packages/common/src/Listeners.ts
  • packages/common/src/Random.ts
  • packages/common/src/Ref.ts
  • packages/common/src/Resource.ts
  • packages/common/src/Resources.ts
  • packages/common/src/Result.ts
  • packages/common/src/Sqlite.ts
  • packages/common/src/Store.ts
  • packages/common/src/StructuralMap.ts
  • packages/common/src/Task.ts
  • packages/common/src/Test.ts
  • packages/common/src/Type.ts
  • packages/common/src/Types.ts
  • packages/common/src/WebSocket.ts
  • packages/common/src/index.ts
  • packages/common/src/local-first/Db.ts
  • packages/common/src/local-first/Evolu.ts
  • packages/common/src/local-first/Relay.ts
  • packages/common/src/local-first/Schema.ts
  • packages/common/src/local-first/Shared.ts
  • packages/common/src/local-first/Sync.ts
  • packages/common/src/local-first/Worker.ts
  • packages/common/test/Assert.test.ts
  • packages/common/test/Buffer.test.ts
  • packages/common/test/Function.test.ts
  • packages/common/test/Listeners.test.ts
  • packages/common/test/Ref.test.ts
  • packages/common/test/Resource.test.ts
  • packages/common/test/Resources.test.ts
  • packages/common/test/Sqlite.test.ts
  • packages/common/test/Store.test.ts
  • packages/common/test/StructuralMap.test.ts
  • packages/common/test/Task.test.ts
  • packages/common/test/TreeShaking.test.ts
  • packages/common/test/Type.test.ts
  • packages/common/test/WebSocket.test.ts
  • packages/common/test/_deps.ts
  • packages/common/test/local-first/Db.internal.test.ts
  • packages/common/test/local-first/Evolu.test.ts
  • packages/common/test/local-first/Shared.test.ts
  • packages/common/test/local-first/Sync.test.ts
  • packages/common/vitest.browser.config.ts
  • packages/common/vitest.unit.config.ts
  • packages/nodejs/package.json
  • packages/nodejs/src/Task.ts
  • packages/nodejs/src/local-first/Relay.ts
  • packages/nodejs/test/Sqlite.test.ts
  • packages/react-native/package.json
  • packages/react-native/src/Task.ts
  • packages/react-native/src/sqlite-drivers/createExpoSqliteDriver.ts
  • packages/react-native/src/sqlite-drivers/createOpSqliteDriver.ts
  • packages/svelte/package.json
  • packages/web/src/Sqlite.ts
  • packages/web/src/Task.ts
  • packages/web/test/Platform.test.ts
  • packages/web/test/Sqlite.test.ts

📝 Walkthrough

Walkthrough

Zavedení nových resource- a lifecycle-API (Resource, SharedResource, ResourceRef), nový strukturálně-klíčovaný StructuralMap, přechod na asynchronní disposal (Symbol.asyncDispose), široké přejmenování Runner→Run a související testy a konfigurace.

Changes

Cohort / File(s) Summary
Core: Resource API
packages/common/src/Resource.ts, packages/common/test/Resource.test.ts
Přidány typy a factory: Resource, BorrowedResource, ResourceRef, SharedResource, SharedResourceByKey a jejich implementace s AsyncDisposableStack, lazy init, ref-counting a idle disposal; rozsáhlé testy.
Structural keys / Map
packages/common/src/StructuralMap.ts, packages/common/test/StructuralMap.test.ts
Nový StructuralMap podporující canonical id pro JSON-like klíče a Uint8Array, WeakMap cache a detekci cyklů; testy pokrývají primitiva, objekty, pole, Uint8Array a chybové stavy.
Run/Task refactor
packages/common/src/Task.ts, packages/nodejs/src/Task.ts, packages/react-native/src/Task.ts, packages/web/src/Task.ts, packages/common/src/Test.ts
Přejmenování Runner→Run / CreateRunner→CreateRun; nové API: Run.asUnabortableDaemon, přechod na CallbackWithTeardown; konverze koncepcí k StructuralKey pro keyed primitiva.
Async disposal across modules
packages/common/src/Sqlite.ts, packages/common/src/WebSocket.ts, packages/common/src/local-first/Sync.ts, packages/web/src/Sqlite.ts, tests...
Přechod ze Symbol.dispose na Symbol.asyncDispose, kontrola assertNotDisposed, disposal awaitování a aktualizace testů/implementací (Sqlite, WebSocket, Sync, atd.).
Store / Listeners / Ref
packages/common/src/Store.ts, packages/common/src/Ref.ts, removed packages/common/src/Listeners.ts, tests...
Ref terminologie změněna „state“→„value“, Store nyní public interface rozšiřující Ref, interní subscriber set místo samostatného createListeners; odpovídající testy aktualizovány/odstraněny.
Type / JSON types
packages/common/src/Type.ts
Rozšíření JSON typů (JsonValue, JsonValueInput, JsonObject, JsonArray atd.) a dokumentace.
Structural changes in local-first
packages/common/src/local-first/*.ts (Db, Evolu, Relay, Shared, Sync, Worker)
Rozšíření storage/relay logiky (quota, timestamps, encryption hooks), přidání transports do EvoluConfig, zjednodušení SharedWorker životního cyklu; množství refaktorů a veřejných exportů/test-hooků.
Index/barrel & exports
packages/common/src/index.ts, packages/common/package.json
Přidán export StructuralMap, odstraněn export Listeners, přidán ./polyfills export a typesVersions záznam.
Tests & config
packages/common/vitest.*.config.ts, .github workflows, many tests
Přejmenování vitest projektů na @evolu/common a @evolu/common (nodejs), aktualizace CI, rozsáhlé testní přidání/úpravy pro nové API a async disposal; některé staré testy odstraněny.
Examples / deps / drivers
package.json, apps/relay/*, packages/*/package.json, packages/*/sqlite-drivers/*
Verzní aktualizace závislostí, refaktory startu relay (AsyncDisposableStack), použití DisposableStack v sqlite driverech a drobné změny v apps/relay start flow.
Docs / tooling
.github/copilot-instructions.md, biome.json, .gitignore
Aktualizovány TDD instrukce, biome schema verze, a .vitest-attachments v .gitignore.

Sequence Diagram(s)

sequenceDiagram
    autonumber
    participant App as App/Client
    participant ResourceRef as ResourceRef
    participant AsyncStack as AsyncDisposableStack
    participant Task as Task/Run

    App->>ResourceRef: get()
    ResourceRef->>Task: vytvoří/vrátí Task<BorrowedResource>
    Task-->>ResourceRef: BorrowedResource (resource + stack)
    ResourceRef-->>App: BorrowedResource

    App->>ResourceRef: set(newCreate)
    ResourceRef->>AsyncStack: dispose(stará resource)
    AsyncStack->>Task: invoke [Symbol.asyncDispose]
    Task-->>AsyncStack: dokončeno
    ResourceRef-->>App: ok

    App->>AsyncStack: dispose()
    AsyncStack->>ResourceRef: [Symbol.asyncDispose]
    ResourceRef-->>AsyncStack: cleanup
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minut

Possibly related PRs

Suggested labels

feat

Suggested reviewers

  • Jakub-coding99

Poem

🐰 Nový Run se protáhl v trávě, stack tichounce zpívá,
asynchronní rozloučení tiše v závětří dýchá.
StructuralMap čísluje klíče, každý tvar pojme rád,
sdílené zdroje hopsají, ref se mění v zázrak.
Hop! Kód skáče dál — evoluce v každém řádku máv.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch dev/astro-6-upgrade

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors resource management across the monorepo, moving several platform/runtime abstractions (SQLite, WebSocket, leader locks, runs) to async disposal patterns and introducing new primitives (e.g., StructuralMap, Resource). It also updates tests and CI configuration to match the new lifecycle semantics and bumps a number of dependencies.

Changes:

  • Switched multiple runtime resources from Symbol.dispose to Symbol.asyncDispose and adopted DisposableStack / AsyncDisposableStack patterns.
  • Introduced StructuralMap (structural-keyed map) and new Resource lifecycle primitives; removed older listener/resource utilities.
  • Updated Vitest project naming/config and refreshed various dependencies and example templates.

Reviewed changes

Copilot reviewed 78 out of 80 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
packages/web/test/Sqlite.test.ts Updates web SQLite tests for async disposal and installs common polyfills.
packages/web/test/Platform.test.ts Simplifies leader lock tests; switches to async disposal.
packages/web/src/Task.ts Refactors web createLeaderLock and renames runner types/APIs to Run.
packages/web/src/Sqlite.ts Uses DisposableStack and improves prepared statement lifecycle/reset behavior.
packages/svelte/package.json Bumps Svelte version and peer dependency floor.
packages/react-native/src/sqlite-drivers/createOpSqliteDriver.ts Wraps op-sqlite driver lifetime in DisposableStack; updates export error message behavior.
packages/react-native/src/sqlite-drivers/createExpoSqliteDriver.ts Wraps expo-sqlite driver lifetime in DisposableStack.
packages/react-native/src/Task.ts Renames createRunnercreateRun and updates docs/aliases for compatibility.
packages/react-native/package.json Bumps op-sqlite and Expo versions.
packages/nodejs/test/Sqlite.test.ts Updates Node.js SQLite tests to use async disposal.
packages/nodejs/src/local-first/Relay.ts Refactors relay startup to use AsyncDisposableStack and updated run/sqlite lifecycle.
packages/nodejs/src/Task.ts Renames createRunnercreateRun and updates docs/aliases for compatibility.
packages/nodejs/package.json Bumps better-sqlite3 and Node type definitions.
packages/common/vitest.unit.config.ts Renames the unit test project for clearer targeting in CI.
packages/common/vitest.browser.config.ts Adjusts browser-instance selection for VS Code Vitest coverage runs; renames project.
packages/common/test/local-first/Sync.test.ts Adds coverage for socket disposal failures during teardown.
packages/common/test/local-first/Shared.test.ts Adds TODO note about switching setup to a Run-with-deps.
packages/common/test/local-first/Evolu.test.ts Updates inline snapshots due to changed deterministic outputs.
packages/common/test/local-first/Db.internal.test.ts Adds assertions for stored-bytes accounting using protocol encoding size.
packages/common/test/_deps.ts Clarifies sqlite driver comment and simplifies helper function body.
packages/common/test/WebSocket.test.ts Adds testCreateWebSocket coverage and converts tests to async disposal.
packages/common/test/Type.test.ts Avoids type/value naming clash in test by renaming local binding.
packages/common/test/TreeShaking.test.ts Updates size baselines for fixtures.
packages/common/test/StructuralMap.test.ts Adds test coverage for new StructuralMap.
packages/common/test/Store.test.ts Adds test ensuring listener notification uses a snapshot during iteration.
packages/common/test/Sqlite.test.ts Updates disposal semantics tests and adds LIKE-wildcard escaping coverage for schema filtering.
packages/common/test/Resources.test.ts Removes legacy resources tests (file deleted).
packages/common/test/Ref.test.ts Renames “state” wording to “value” in test names.
packages/common/test/Listeners.test.ts Removes Listeners tests (file deleted).
packages/common/test/Function.test.ts Removes Function utilities tests tied to removed readonly helper (file deleted).
packages/common/test/Buffer.test.ts Updates assertions to use toThrow consistently.
packages/common/test/Assert.test.ts Adds coverage for assertNotAborted / assertNotDisposed and improves typing assertions.
packages/common/src/local-first/Worker.ts Refactors subscription teardown logic in deprecated worker init.
packages/common/src/local-first/Sync.ts Moves WebSocket resources to async disposal with best-effort error logging on disposal.
packages/common/src/local-first/Shared.ts Removes transport resource abstraction and adjusts shared worker lifecycle handling.
packages/common/src/local-first/Schema.ts Removes readonly helper usage and makes exported sets/arrays explicitly readonly-typed.
packages/common/src/local-first/Relay.ts Refactors quota/write logic and modifies relay storage table creation semantics.
packages/common/src/local-first/Evolu.ts Refactors Evolu config docs, export typing, error-store handling, and disposal stack usage.
packages/common/src/local-first/Db.ts Refactors DB worker init/storage logic, adds client storage helpers, and updates timestamp/quota handling.
packages/common/src/index.ts Removes Listeners export; re-exports new Resource and StructuralMap modules; adjusts type exports.
packages/common/src/WebSocket.ts Makes WebSocket async-disposable, improves ready-state mapping and expands testCreateWebSocket.
packages/common/src/Types.ts Renames CallbackWithCleanupCallbackWithTeardown.
packages/common/src/Type.ts Expands orThrow documentation and adds JsonValue / JsonValueInput docs.
packages/common/src/Test.ts Renames test runner helpers (testCreateRun) and updates deterministic test helper APIs.
packages/common/src/StructuralMap.ts Adds StructuralMap implementation for structural-key registries (new file).
packages/common/src/Store.ts Inlines listener management and snapshot notification; removes dependency on Listeners.
packages/common/src/Sqlite.ts Makes Sqlite async-disposable, adds disposed-guarding for sync methods, and improves schema snapshot options.
packages/common/src/Result.ts Refines documentation wording for Result composition and getOrThrow.
packages/common/src/Resources.ts Extends resources to dispose both sync and async disposables; adjusts overload implementation.
packages/common/src/Resource.ts Adds new resource lifecycle primitives (ResourceRef, SharedResource, keyed shared resources) (new file).
packages/common/src/Ref.ts Clarifies immutability expectations in docs and renames state/value terminology.
packages/common/src/Random.ts Refactors Arc4 snapshot typing into a named interface.
packages/common/src/Listeners.ts Removes Listeners implementation (file deleted).
packages/common/src/Function.ts Removes readonly helper and related type-only imports.
packages/common/src/Assert.ts Adds assertNotAborted and assertNotDisposed.
packages/common/src/Polyfills.ts Adds installPolyfills and owned DisposableStack polyfill logic.
packages/common/package.json Adds ./polyfills export and bumps Kysely/better-sqlite3.
package.json Bumps Biome and Turbo.
examples/vue-vite-pwa/package.json Bumps @vitejs/plugin-vue.
examples/tauri/package.json Bumps @vitejs/plugin-react.
examples/tanstack-start/package.json Bumps TanStack Router and @vitejs/plugin-react.
examples/svelte-vite-pwa/package.json Bumps Svelte.
examples/react-vite-pwa/package.json Bumps @vitejs/plugin-react.
examples/react-nextjs/package.json Bumps Next.js and Node types.
examples/react-expo/package.json Bumps Expo-related dependencies.
examples/react-electron/package.json Bumps @vitejs/plugin-react and electron vite plugins.
examples/astro/package.json Bumps Astro + React integration and adds @astrojs/check.
examples/angular-vite-pwa/package.json Bumps Angular packages.
biome.json Updates Biome schema URL to match bumped Biome version.
apps/relay/src/startBunRelay.ts Refactors relay startup stack usage and sqlite acquisition; simplifies shutdown defers.
apps/relay/src/index.ts Switches relay startup to createRun and removes Bun-runtime branching.
apps/relay/package.json Bumps Node types.
.gitignore Ignores .vitest-attachments.
.github/workflows/ws-browser-nightly.yaml Updates Vitest project name used in nightly browser WebSocket tests.
.github/workflows/ci.yaml Updates Vitest project name used in CI smoke tests.
.github/copilot-instructions.md Updates testing guidance wording.
.changeset/structural-map-uint8array.md Adds changeset for StructuralMap minor release.
Comments suppressed due to low confidence (1)

packages/common/src/local-first/Relay.ts:321

  • createRelayStorageTables is no longer idempotent (create table instead of create table if not exists). This breaks callers that run table creation on every startup (e.g. apps/relay/src/startBunRelay.ts currently calls it unconditionally) and makes repeated initialization fail. Restore if not exists (or otherwise ensure callers only run this on a fresh DB).

Comment on lines 34 to 77
@@ -67,11 +73,14 @@ export const createLeaderLock = (): LeaderLock => ({

if (state === "failed") {
release.resolve();
return run(inMemoryLeaderLock.acquire(name));
return run(unabortable(inMemoryLeaderLock.lock(name)));
}
Comment on lines 1 to 30
import { Name, testName } from "@evolu/common";
import { afterEach, describe, expect, test, vi } from "vitest";
import { describe, expect, test } from "vitest";
import { createLeaderLock, createRun } from "../src/Task.js";

afterEach(() => {
vi.restoreAllMocks();
});

const withNavigator = async (
navigator: typeof globalThis.navigator | undefined,
runTest: () => Promise<void>,
): Promise<void> => {
const originalNavigator = globalThis.navigator;
describe("leaderLock", () => {
test("acquire waits until previous lease is disposed", async () => {
await using run = createRun();
const leaderLock = createLeaderLock();

Object.defineProperty(globalThis, "navigator", {
configurable: true,
writable: true,
value: navigator,
});
const first = await run(leaderLock.lock(testName));
expect(first.ok).toBe(true);
if (!first.ok) return;

try {
await runTest();
} finally {
Object.defineProperty(globalThis, "navigator", {
configurable: true,
writable: true,
value: originalNavigator,
let secondSettled = false;
const second = run(leaderLock.lock(testName));
void second.then(() => {
secondSettled = true;
});
}
};

const expectSequentialAcquireForSameName = async (): Promise<void> => {
await using run = createRun();
const leaderLock = createLeaderLock();

const first = await run(leaderLock.acquire(testName));
expect(first.ok).toBe(true);
if (!first.ok) return;

let secondSettled = false;
const second = run(leaderLock.acquire(testName));
void second.then(() => {
secondSettled = true;
});

await Promise.resolve();
expect(secondSettled).toBe(false);

first.value[Symbol.dispose]();
await Promise.resolve();
expect(secondSettled).toBe(false);

const secondResult = await second;
expect(secondResult.ok).toBe(true);
if (!secondResult.ok) return;
await first.value[Symbol.asyncDispose]();

secondResult.value[Symbol.dispose]();
};
const secondResult = await second;
expect(secondResult.ok).toBe(true);
if (!secondResult.ok) return;

describe("leaderLock", () => {
test("acquire waits until previous lease is disposed", async () => {
await expectSequentialAcquireForSameName();
await secondResult.value[Symbol.asyncDispose]();
});
Comment on lines +7 to +9
import { assert } from "./Assert.js";
import { isPlainObject } from "./Object.js";
import { type JsonValue, uint8ArrayToBase64Url } from "./Type.js";
Comment on lines +161 to 164
const lifetime = run.create();
lifetime.onAbort(() => {
unsubscribe();
return ok();
});
Comment on lines +542 to 544
// eslint-disable-next-line @typescript-eslint/require-await
[Symbol.asyncDispose]: async () => {
if (appOwner) {
await run(transports.removeConsumer(appOwner, ownerTransports));
}

clearActiveLeaderTimeout();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

fix Repair any bug update Update libs and deps upstream Needs cherry-pick or merge from upstream

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants