@tearleads/client-sdk 0.1.81 → 0.1.84
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/client/organizations/organizationReadModels.js +4 -2
- package/client/organizations/organizationReadModels.js.map +1 -1
- package/data/documents/documentSync.js.map +1 -1
- package/data/documents/shared/crypto.js.map +1 -1
- package/data/documents/shared/types.d.ts +1 -1
- package/data/documents/shared/types.js.map +1 -1
- package/data/persistence/container-contents/containerContentsPersistence.js +2 -2
- package/data/persistence/container-contents/containerContentsPersistence.js.map +1 -1
- package/data/persistence/container-contents/containerContentsPersistenceTypes.d.ts +1 -1
- package/data/persistence/container-contents/containerContentsPersistenceTypes.js.map +1 -1
- package/data/persistence/container-contents/containerDeletionPersistence.js +1 -1
- package/data/persistence/container-contents/containerDeletionPersistence.js.map +1 -1
- package/data/persistence/container-contents/containerMetadataMutationPersistence.js +3 -3
- package/data/persistence/container-contents/containerMetadataMutationPersistence.js.map +1 -1
- package/data/persistence/container-contents/containerMetadataPullContinuationPersistence.js +1 -1
- package/data/persistence/container-contents/containerMetadataPullContinuationPersistence.js.map +1 -1
- package/data/persistence/container-contents/containerMetadataRows.js +1 -1
- package/data/persistence/container-contents/containerMetadataRows.js.map +1 -1
- package/data/persistence/container-contents/containerPendingUpdatePersistence.js +2 -2
- package/data/persistence/container-contents/containerPendingUpdatePersistence.js.map +1 -1
- package/data/persistence/container-contents/containerReconcilePersistence.js +1 -1
- package/data/persistence/container-contents/containerReconcilePersistence.js.map +1 -1
- package/data/persistence/container-contents/containerRemovalWork.js +1 -1
- package/data/persistence/container-contents/containerRemovalWork.js.map +1 -1
- package/data/persistence/documents/documentDiscoveryReset.d.ts +6 -0
- package/data/persistence/documents/documentsPersistence.js +2 -2
- package/data/persistence/documents/documentsPersistence.js.map +1 -1
- package/data/persistence/documents/internal/createDocumentWithHistoryCheckpoint.js +1 -1
- package/data/persistence/documents/internal/createDocumentWithHistoryCheckpoint.js.map +1 -1
- package/data/persistence/documents/internal/discardDocument.js +2 -2
- package/data/persistence/documents/internal/discardDocument.js.map +1 -1
- package/data/persistence/documents/internal/documentDeletionPersistence.js +2 -2
- package/data/persistence/documents/internal/documentDeletionPersistence.js.map +1 -1
- package/data/persistence/documents/internal/documentMutationPersistence.js +3 -3
- package/data/persistence/documents/internal/documentMutationPersistence.js.map +1 -1
- package/data/persistence/documents/internal/documentPullContinuationPersistence.js +1 -1
- package/data/persistence/documents/internal/documentPullContinuationPersistence.js.map +1 -1
- package/data/persistence/documents/internal/documentRecordIdentity.js.map +1 -1
- package/data/persistence/documents/internal/documentRows.js.map +1 -1
- package/data/persistence/documents/internal/ensureDocumentsSchema.js +1 -1
- package/data/persistence/documents/internal/ensureDocumentsSchema.js.map +1 -1
- package/data/persistence/documents/internal/orphanSideRows.js +1 -1
- package/data/persistence/documents/internal/orphanSideRows.js.map +1 -1
- package/data/persistence/documents/internal/rowQueryPersistence.js +1 -1
- package/data/persistence/documents/internal/rowQueryPersistence.js.map +1 -1
- package/data/persistence/documents/internal/syncQueuePersistence.js +2 -2
- package/data/persistence/documents/internal/syncQueuePersistence.js.map +1 -1
- package/data/{sqlite/documentPersistence → persistence/documents/records}/documentHistoryPersistence.d.ts +1 -1
- package/data/{sqlite/documentPersistence → persistence/documents/records}/documentHistoryPersistence.js +5 -5
- package/data/persistence/documents/records/documentHistoryPersistence.js.map +1 -0
- package/data/{sqlite/documentPersistence → persistence/documents/records}/documentPendingUpdatePersistence.d.ts +2 -2
- package/data/{sqlite/documentPersistence → persistence/documents/records}/documentPendingUpdatePersistence.js +2 -2
- package/data/persistence/documents/records/documentPendingUpdatePersistence.js.map +1 -0
- package/data/{sqlite/documentPersistence → persistence/documents/records}/documentPersistenceTypes.d.ts +2 -2
- package/data/persistence/documents/records/documentPersistenceTypes.js.map +1 -0
- package/data/{sqlite/documentPersistence → persistence/documents/records}/documentRecordPersistence.d.ts +1 -1
- package/data/{sqlite/documentPersistence → persistence/documents/records}/documentRecordPersistence.js +4 -4
- package/data/persistence/documents/records/documentRecordPersistence.js.map +1 -0
- package/data/{sqlite/documentPersistence → persistence/documents/records}/documentSyncFailurePersistence.d.ts +2 -2
- package/data/{sqlite/documentPersistence → persistence/documents/records}/documentSyncFailurePersistence.js +3 -3
- package/data/persistence/documents/records/documentSyncFailurePersistence.js.map +1 -0
- package/data/{sqlite/documentPersistence → persistence/documents/records}/index.d.ts +2 -2
- package/data/{sqlite/documentPersistence → persistence/documents/records}/index.js +4 -4
- package/data/persistence/documents/records/index.js.map +1 -0
- package/data/persistence/documents/types.d.ts +2 -2
- package/data/persistence/documents/types.js.map +1 -1
- package/{workflows/sync/remoteResetPrincipalScope.d.ts → data/persistence/principalPolicy/principalPolicyRemoteReset.d.ts} +1 -1
- package/{workflows/sync/remoteResetPrincipalScope.js → data/persistence/principalPolicy/principalPolicyRemoteReset.js} +7 -7
- package/data/persistence/principalPolicy/principalPolicyRemoteReset.js.map +1 -0
- package/data/persistence/verifiedManifestBundlePersistence.d.ts +2 -0
- package/data/persistence/verifiedManifestBundlePersistence.js +7 -0
- package/data/persistence/verifiedManifestBundlePersistence.js.map +1 -1
- package/data/sqlite/{documentPersistence/documentOrphanBlobReclaims.js → schema/documentOrphanBlobReclaimSchema.js} +1 -1
- package/data/sqlite/schema/documentOrphanBlobReclaimSchema.js.map +1 -0
- package/data/sqlite/schema/index.js +1 -1
- package/data/sqlite/schema/index.js.map +1 -1
- package/data/sqlite/sqliteBindBudget.js +12 -0
- package/data/sqlite/sqliteBindBudget.js.map +1 -1
- package/package.json +1 -1
- package/workflows/container-contents/container-state/create/createIntentSeed.js.map +1 -1
- package/workflows/container-contents/container-state/create/createWithMetadataPlan.js.map +1 -1
- package/workflows/container-contents/container-state/types.js.map +1 -1
- package/workflows/container-contents/metadata/index.js.map +1 -1
- package/workflows/container-contents/metadata/metadataEvents.d.ts +1 -1
- package/workflows/container-contents/metadata/metadataEvents.js.map +1 -1
- package/workflows/container-contents/metadata/metadataIncomingUpdateIsolation.js +1 -1
- package/workflows/container-contents/metadata/metadataIncomingUpdateIsolation.js.map +1 -1
- package/workflows/container-contents/metadata/metadataRemoteSync.d.ts +1 -1
- package/workflows/container-contents/metadata/metadataRemoteSync.js.map +1 -1
- package/workflows/container-contents/pendingWrites/index.js +1 -1
- package/workflows/container-contents/pendingWrites/index.js.map +1 -1
- package/{client/organizations/organizationAccessRestoration.js → workflows/container-contents/recovery/accessRestoration.js} +16 -12
- package/workflows/container-contents/recovery/accessRestoration.js.map +1 -0
- package/workflows/container-contents/remoteReset/containerRemoteReset.d.ts +185 -0
- package/workflows/container-contents/remoteReset/containerRemoteReset.js +174 -0
- package/workflows/container-contents/remoteReset/containerRemoteReset.js.map +1 -0
- package/workflows/container-contents/remoteReset/remoteResetCursorScope.d.ts +14 -0
- package/workflows/{sync → container-contents/remoteReset}/remoteResetCursorScope.js +2 -2
- package/workflows/container-contents/remoteReset/remoteResetCursorScope.js.map +1 -0
- package/workflows/documents/create/documentCreationPersistence.js.map +1 -1
- package/workflows/documents/create/index.d.ts +1 -1
- package/workflows/documents/create/index.js.map +1 -1
- package/workflows/documents/documentMutationCommit.d.ts +1 -1
- package/workflows/documents/documentMutationCommit.js.map +1 -1
- package/workflows/documents/index.d.ts +2 -2
- package/workflows/documents/index.js +2 -2
- package/workflows/documents/index.js.map +1 -1
- package/workflows/documents/remoteReset/documentRemoteReset.d.ts +56 -0
- package/workflows/documents/remoteReset/documentRemoteReset.js +135 -0
- package/workflows/documents/remoteReset/documentRemoteReset.js.map +1 -0
- package/workflows/{sync → documents/remoteReset}/remoteResetAttachments.js +3 -3
- package/workflows/documents/remoteReset/remoteResetAttachments.js.map +1 -0
- package/workflows/{sync → documents/remoteReset}/remoteResetPlans.d.ts +1 -1
- package/workflows/{sync → documents/remoteReset}/remoteResetPlans.js +7 -7
- package/workflows/documents/remoteReset/remoteResetPlans.js.map +1 -0
- package/workflows/documents/sync/index.js.map +1 -1
- package/workflows/documents/sync/initialSync.d.ts +1 -1
- package/workflows/documents/sync/initialSync.js.map +1 -1
- package/workflows/documents/sync/readOnlySync.d.ts +1 -1
- package/workflows/documents/sync/readOnlySync.js.map +1 -1
- package/workflows/documents/sync/syncAttemptPlanning.js.map +1 -1
- package/workflows/documents/sync/syncAttemptState.d.ts +1 -1
- package/workflows/documents/sync/syncAttemptState.js.map +1 -1
- package/workflows/documents/sync/syncResponseResult.js.map +1 -1
- package/workflows/documents/sync/syncSubmittedResult.js.map +1 -1
- package/workflows/documents/syncFailures/index.js.map +1 -1
- package/workflows/documents/syncPlan/syncContentKeys.d.ts +1 -1
- package/workflows/documents/syncPlan/syncContentKeys.js.map +1 -1
- package/workflows/documents/syncPlan/syncPlanMaterial.js.map +1 -1
- package/workflows/documents/syncPlan/syncPlanRequestBounds.js.map +1 -1
- package/workflows/documents/syncRekeys/syncContainerRekeys.js.map +1 -1
- package/workflows/documents/syncRekeys/syncRecoveryRekey.d.ts +1 -1
- package/workflows/documents/syncRekeys/syncRecoveryRekey.js +1 -1
- package/workflows/documents/syncRekeys/syncRecoveryRekey.js.map +1 -1
- package/workflows/organizations/readModel/listLocalOrganizations.js +1 -1
- package/workflows/organizations/readModel/listLocalOrganizations.js.map +1 -1
- package/workflows/organizations/readModel/organizationRemoteReset.js +25 -0
- package/workflows/organizations/readModel/organizationRemoteReset.js.map +1 -0
- package/workflows/registration/persistRegistrationBootstrap.d.ts +1 -1
- package/workflows/registration/persistRegistrationBootstrap.js.map +1 -1
- package/workflows/sync/remoteReset.js +60 -229
- package/workflows/sync/remoteReset.js.map +1 -1
- package/workflows/sync/remoteResetScope.d.ts +7 -10
- package/workflows/sync/remoteResetScope.js +26 -108
- package/workflows/sync/remoteResetScope.js.map +1 -1
- package/client/organizations/organizationAccessRestoration.js.map +0 -1
- package/data/sqlite/documentPersistence/documentHistoryPersistence.js.map +0 -1
- package/data/sqlite/documentPersistence/documentOrphanBlobReclaims.js.map +0 -1
- package/data/sqlite/documentPersistence/documentPendingUpdatePersistence.js.map +0 -1
- package/data/sqlite/documentPersistence/documentPersistenceTypes.js.map +0 -1
- package/data/sqlite/documentPersistence/documentRecordPersistence.js.map +0 -1
- package/data/sqlite/documentPersistence/documentSyncFailurePersistence.js.map +0 -1
- package/data/sqlite/documentPersistence/index.js.map +0 -1
- package/workflows/sync/remoteResetAttachments.js.map +0 -1
- package/workflows/sync/remoteResetBatches.js +0 -13
- package/workflows/sync/remoteResetBatches.js.map +0 -1
- package/workflows/sync/remoteResetCursorScope.js.map +0 -1
- package/workflows/sync/remoteResetPlans.js.map +0 -1
- package/workflows/sync/remoteResetPrincipalScope.js.map +0 -1
- /package/data/{sqlite/documentPersistence → persistence/documents/records}/documentPersistenceTypes.js +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"remoteReset.js","sourceRoot":"","sources":["remoteReset.ts"],"names":[],"mappings":"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","sourcesContent":["import { and, eq, inArray, or } from \"drizzle-orm\";\nimport {\n deleteDocumentPlacementRowsByContainerIds,\n deleteDocumentPlacementRowsByDocumentIds,\n} from \"../../data/persistence/container-contents/documentContainerProjectionPersistence\";\nimport { recordSupersededContainerBindingsInTransaction } from \"../../data/persistence/container-contents/supersededContainerBindings\";\nimport { clearDocumentDiscoveryEvidenceOnRemoteReset } from \"../../data/persistence/documents/documentDiscoveryReset\";\nimport {\n queuedUpdateRow,\n unqueueDocumentScopesInTransaction,\n} from \"../../data/sqlite/documentPersistence/documentPendingUpdatePersistence\";\nimport { CLEARED_DOCUMENT_SYNC_FAILURE } from \"../../data/sqlite/documentPersistence/documentSyncFailurePersistence\";\nimport {\n clientSqlTables,\n containerHydrationTombstones,\n containers,\n documentAttachmentBlobProjection,\n documentHistoryUpdates,\n documentPendingAttachments,\n documentProjection,\n documents,\n dormantContainerMetadata,\n dormantMetadataSweepRequests,\n inContainerIntentLanes,\n inLocalIntentLane,\n LOCAL_INTENT_LANES,\n localIntents,\n} from \"../../data/sqlite/schema\";\nimport { documentIntentLinkTargets } from \"../../data/sqlite/schema/documentPlacementIntentSchema\";\nimport { organizationDataUsageSnapshots } from \"../../data/sqlite/schema/organizationDataUsageSchema\";\nimport {\n organizationPresentationDenials,\n organizationReadModelContainerGrants,\n organizationReadModelDirectoryUsers,\n organizationReadModelGroupMembers,\n organizationReadModelGroups,\n organizationReadModelRequesters,\n organizationReadModelState,\n} from \"../../data/sqlite/schema/organizationReadModelSchema\";\nimport { verifiedAccessManifestBundles } from \"../../data/sqlite/schema/verifiedManifestBundleSchema\";\nimport {\n type ClientSQLiteTransactionScope,\n getClientSQLitePersistenceRuntime,\n} from \"../../data/sqlite/sqlitePersistenceRuntime\";\nimport type { ExecSql } from \"../../data/sqlite/sqlSchema\";\nimport { ensureSqlTables } from \"../../data/sqlite/sqlTableSchema\";\nimport { runOrganizationPresentationReset } from \"../organizations/readModel/organizationPresentationAccessState\";\nimport { clearResetPendingAttachments } from \"./remoteResetAttachments\";\nimport { remoteResetBatches } from \"./remoteResetBatches\";\nimport { clearRemoteResetSyncCursors } from \"./remoteResetCursorScope\";\nimport {\n buildResetPlans,\n type ResetAttachmentUpload,\n type ResetDocumentUpdate,\n} from \"./remoteResetPlans\";\nimport { clearRemoteResetPrincipalRows } from \"./remoteResetPrincipalScope\";\nimport {\n type RemoteResetInput,\n type RemoteSyncStateSnapshot,\n readRemoteSyncStateSnapshot,\n} from \"./remoteResetScope\";\n\nexport type {\n RemoteResetInput,\n RemoteResetReplacement,\n} from \"./remoteResetScope\";\n\nconst CONTAINER_CREATE_INTENT_TYPE = \"container.create\";\n\nexport interface ClearRemoteSyncStateResult {\n readonly clearedContainerCreateIntentCount: number;\n readonly clearedContainerMoveIntentCount: number;\n readonly clearedDocumentMoveIntentCount: number;\n readonly clearedPrincipalPolicyCount: number;\n readonly clearedSyncCursorCount: number;\n readonly queuedAttachmentUploadCount: number;\n readonly queuedContainerCreateCount: number;\n readonly queuedDocumentUpdateCount: number;\n readonly resetContainerCount: number;\n readonly resetDocumentCount: number;\n}\n\nasync function clearOrganizationPresentationRows(\n tx: ClientSQLiteTransactionScope,\n organizationId: string,\n): Promise<void> {\n for (const table of [\n organizationDataUsageSnapshots,\n organizationReadModelContainerGrants,\n organizationReadModelGroupMembers,\n organizationReadModelDirectoryUsers,\n organizationReadModelGroups,\n organizationReadModelRequesters,\n organizationReadModelState,\n organizationPresentationDenials,\n ] as const) {\n await tx\n .delete(table)\n .where(eq(table.organizationId, organizationId))\n .run();\n }\n}\n\ninterface ScopedRemoteRowsInput {\n attachmentUploads: readonly ResetAttachmentUpload[];\n organizationId: string;\n snapshot: RemoteSyncStateSnapshot;\n tx: ClientSQLiteTransactionScope;\n}\n\nasync function clearScopedContainerRows(\n input: ScopedRemoteRowsInput,\n): Promise<void> {\n for (const containerBatch of remoteResetBatches(\n input.snapshot.containerIds,\n )) {\n await deleteDocumentPlacementRowsByContainerIds(input.tx, containerBatch);\n await input.tx\n .delete(localIntents)\n .where(\n and(\n inContainerIntentLanes(),\n inArray(localIntents.subjectId, containerBatch),\n ),\n )\n .run();\n await input.tx\n .delete(containerHydrationTombstones)\n .where(inArray(containerHydrationTombstones.containerId, containerBatch))\n .run();\n }\n}\n\nasync function clearScopedDocumentRows(\n input: ScopedRemoteRowsInput,\n): Promise<void> {\n const { snapshot, tx } = input;\n for (const documentIdBatch of remoteResetBatches(snapshot.oldDocumentIds)) {\n await deleteDocumentPlacementRowsByDocumentIds(tx, documentIdBatch);\n }\n await clearResetPendingAttachments({\n attachmentUploads: input.attachmentUploads,\n documentLocalIds: snapshot.documentLocalIds,\n tx,\n });\n for (const localIdBatch of remoteResetBatches(snapshot.documentLocalIds)) {\n const placementIntents = and(\n inLocalIntentLane(LOCAL_INTENT_LANES.documentPlacement),\n inArray(localIntents.localId, localIdBatch),\n );\n await tx\n .delete(documentIntentLinkTargets)\n .where(\n inArray(\n documentIntentLinkTargets.intentId,\n tx\n .select({ id: localIntents.id })\n .from(localIntents)\n .where(placementIntents),\n ),\n )\n .run();\n await tx.delete(localIntents).where(placementIntents).run();\n }\n // Sync failures clear with the document columns in resetRemoteColumns.\n for (const documentBatch of remoteResetBatches(snapshot.documentRows)) {\n await unqueueDocumentScopesInTransaction(tx, documentBatch);\n }\n}\n\nasync function clearScopedRemoteRows(\n input: ScopedRemoteRowsInput,\n): Promise<void> {\n const { organizationId, tx } = input;\n await clearOrganizationPresentationRows(tx, organizationId);\n for (const table of [\n dormantContainerMetadata,\n dormantMetadataSweepRequests,\n verifiedAccessManifestBundles,\n ] as const) {\n await tx\n .delete(table)\n .where(eq(table.organizationId, organizationId))\n .run();\n }\n await clearDocumentDiscoveryEvidenceOnRemoteReset(tx, {\n containerIds: input.snapshot.containerIds,\n documentIds: input.snapshot.oldDocumentIds,\n });\n await clearRemoteResetPrincipalRows(input);\n await clearScopedContainerRows(input);\n await clearScopedDocumentRows(input);\n await clearRemoteResetSyncCursors({\n containerIds: input.snapshot.containerIds,\n tx,\n });\n}\n\nasync function resetRemoteColumns(input: {\n now: string;\n reset: RemoteResetInput;\n snapshot: RemoteSyncStateSnapshot;\n tx: ClientSQLiteTransactionScope;\n}): Promise<void> {\n const { now, reset, snapshot, tx } = input;\n for (const row of snapshot.documentRows) {\n await tx\n .update(documents)\n .set({\n accessEpoch: 1,\n accessStateHash: null,\n contentKeyBundle: null,\n documentId: null,\n documentKekTargets: null,\n documentManifestBundle: null,\n lastCommitLsn: null,\n pullContinuation: null,\n recoveryDocumentId: row.documentId ?? row.recoveryDocumentId,\n ...CLEARED_DOCUMENT_SYNC_FAILURE,\n updatedAt: now,\n })\n .where(\n and(\n eq(documents.appKind, row.appKind),\n eq(documents.localId, row.localId),\n ),\n )\n .run();\n }\n for (const localIdBatch of remoteResetBatches(snapshot.documentLocalIds)) {\n await tx\n .update(documentProjection)\n .set({\n documentId: null,\n organizationId:\n reset.replacement?.organizationId ?? reset.organizationId,\n })\n .where(inArray(documentProjection.localId, localIdBatch))\n .run();\n }\n // Replacement re-homes folders under their ids; the purged organization\n // can never bind them again on this device.\n for (const containerIds of reset.replacement\n ? remoteResetBatches(snapshot.containerIds)\n : []) {\n await recordSupersededContainerBindingsInTransaction(tx, {\n containerIds,\n organizationId: reset.organizationId,\n supersededAt: now,\n });\n }\n for (const row of snapshot.containerRows) {\n await tx\n .update(containers)\n .set({\n metadataDocumentId: null,\n organizationId:\n reset.replacement?.organizationId ?? reset.organizationId,\n parentId:\n reset.replacement && row.parentId === null\n ? reset.replacement.rootContainerId\n : row.parentId,\n serverCreatedAt: null,\n serverUpdatedAt: null,\n ...(reset.replacement ? { systemSlot: null } : {}),\n localUpdatedAt: now,\n })\n .where(eq(containers.id, row.id))\n .run();\n }\n}\n\nasync function queueResetDocumentUpdates(input: {\n documentUpdates: readonly ResetDocumentUpdate[];\n now: string;\n tx: ClientSQLiteTransactionScope;\n}): Promise<void> {\n for (const updateBatch of remoteResetBatches(input.documentUpdates)) {\n await input.tx\n .insert(documentHistoryUpdates)\n .values(\n updateBatch.map((update) =>\n queuedUpdateRow({\n createdAt: input.now,\n origin: \"outbox\",\n pendingUpdate: update,\n scope: update,\n updateId: crypto.randomUUID(),\n }),\n ),\n )\n .run();\n }\n}\n\nasync function queueResetContainerCreates(input: {\n now: string;\n reset: RemoteResetInput;\n snapshot: RemoteSyncStateSnapshot;\n tx: ClientSQLiteTransactionScope;\n}): Promise<number> {\n const rows = input.snapshot.containerRows.flatMap((row) => {\n const parentId =\n row.parentId ?? input.reset.replacement?.rootContainerId ?? null;\n return parentId ? [{ id: row.id, parentId }] : [];\n });\n if (rows.length === 0) return 0;\n for (const rowBatch of remoteResetBatches(rows)) {\n await input.tx\n .insert(localIntents)\n .values(\n rowBatch.map((row) => ({\n id: crypto.randomUUID(),\n lane: LOCAL_INTENT_LANES.containerCreate,\n subjectId: row.id,\n targetContainerId: row.parentId,\n intentType: CONTAINER_CREATE_INTENT_TYPE,\n syncStatus: \"pending\" as const,\n remoteContainerId: null,\n remoteMetadataAccessStateHash: null,\n remoteMetadataDocumentId: null,\n lastError: null,\n createdAt: input.now,\n updatedAt: input.now,\n })),\n )\n .run();\n }\n return rows.length;\n}\n\nasync function queueResetAttachmentUploads(input: {\n attachmentUploads: readonly ResetAttachmentUpload[];\n now: string;\n tx: ClientSQLiteTransactionScope;\n}): Promise<void> {\n for (const attachmentBatch of remoteResetBatches(input.attachmentUploads)) {\n await input.tx\n .insert(documentPendingAttachments)\n .values(\n attachmentBatch.map((attachment) => ({\n ...attachment,\n createdAt: input.now,\n })),\n )\n .run();\n await input.tx\n .delete(documentAttachmentBlobProjection)\n .where(\n or(\n ...attachmentBatch.map((attachment) =>\n and(\n eq(documentAttachmentBlobProjection.localId, attachment.localId),\n eq(documentAttachmentBlobProjection.slotId, attachment.slotId),\n ),\n ),\n ),\n )\n .run();\n }\n}\n\nasync function clearRemoteSyncStateInTransaction(input: {\n plans: Awaited<ReturnType<typeof buildResetPlans>>;\n reset: RemoteResetInput;\n snapshot: RemoteSyncStateSnapshot;\n tx: ClientSQLiteTransactionScope;\n}): Promise<ClearRemoteSyncStateResult> {\n const now = new Date().toISOString();\n const { snapshot } = input;\n await clearScopedRemoteRows({\n attachmentUploads: input.plans.attachmentUploads,\n organizationId: input.reset.organizationId,\n snapshot,\n tx: input.tx,\n });\n await resetRemoteColumns({ now, reset: input.reset, snapshot, tx: input.tx });\n await queueResetDocumentUpdates({\n documentUpdates: input.plans.documentUpdates,\n now,\n tx: input.tx,\n });\n const queuedContainerCreateCount = await queueResetContainerCreates({\n now,\n reset: input.reset,\n snapshot,\n tx: input.tx,\n });\n await queueResetAttachmentUploads({\n attachmentUploads: input.plans.attachmentUploads,\n now,\n tx: input.tx,\n });\n return {\n clearedContainerCreateIntentCount:\n snapshot.clearedContainerCreateIntentCount,\n clearedContainerMoveIntentCount: snapshot.clearedContainerMoveIntentCount,\n clearedDocumentMoveIntentCount: snapshot.clearedDocumentMoveIntentCount,\n clearedPrincipalPolicyCount: snapshot.clearedPrincipalPolicyCount,\n clearedSyncCursorCount: snapshot.clearedSyncCursorCount,\n queuedAttachmentUploadCount: input.plans.attachmentUploads.length,\n queuedContainerCreateCount,\n queuedDocumentUpdateCount: input.plans.documentUpdates.length,\n resetContainerCount: snapshot.containerRows.length,\n resetDocumentCount: snapshot.documentRows.length,\n };\n}\n\nexport async function clearRemoteSyncState(\n execSql: ExecSql,\n reset: RemoteResetInput,\n canCommit?: (() => boolean) | undefined,\n): Promise<ClearRemoteSyncStateResult> {\n return runOrganizationPresentationReset(\n execSql,\n reset.organizationId,\n async () => {\n await ensureSqlTables(execSql, clientSqlTables);\n const runtime = getClientSQLitePersistenceRuntime(execSql);\n const resetInTransaction = async (tx: ClientSQLiteTransactionScope) => {\n if (canCommit && !canCommit()) {\n throw new Error(\n \"Remote sync reset aborted: session identity changed\",\n );\n }\n const snapshot = await readRemoteSyncStateSnapshot(\n tx,\n reset.organizationId,\n );\n const plans = await buildResetPlans(tx, snapshot.documentRows);\n return clearRemoteSyncStateInTransaction({\n plans,\n reset,\n snapshot,\n tx,\n });\n };\n if (!canCommit) {\n return runtime.transaction(resetInTransaction);\n }\n const outcome = await runtime.guardedTransaction(\n resetInTransaction,\n canCommit,\n );\n if (!outcome.committed || !outcome.result) {\n throw new Error(\"Remote sync reset aborted: session identity changed\");\n }\n return outcome.result;\n },\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"remoteReset.js","sourceRoot":"","sources":["remoteReset.ts"],"names":[],"mappings":"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","sourcesContent":["import { clearRemoteResetPrincipalRows } from \"../../data/persistence/principalPolicy/principalPolicyRemoteReset\";\nimport { deleteVerifiedManifestBundlesForOrganization } from \"../../data/persistence/verifiedManifestBundlePersistence\";\nimport { clientSqlTables } from \"../../data/sqlite/schema\";\nimport {\n type ClientSQLiteTransactionScope,\n getClientSQLitePersistenceRuntime,\n} from \"../../data/sqlite/sqlitePersistenceRuntime\";\nimport type { ExecSql } from \"../../data/sqlite/sqlSchema\";\nimport { ensureSqlTables } from \"../../data/sqlite/sqlTableSchema\";\nimport {\n clearContainerRowsForRemoteReset,\n clearDocumentPlacementsForRemoteReset,\n clearDormantContainerMetadataForRemoteReset,\n clearRemoteResetSyncCursors,\n queueContainerCreatesForRemoteReset,\n resetContainerServerIdentity,\n} from \"../container-contents/remoteReset/containerRemoteReset\";\nimport {\n buildResetPlans,\n clearDocumentDiscoveryEvidenceOnRemoteReset,\n clearDocumentRowsForRemoteReset,\n queueAttachmentReuploadsForRemoteReset,\n queueDocumentRepublishForRemoteReset,\n resetDocumentServerIdentity,\n} from \"../documents/remoteReset/documentRemoteReset\";\nimport {\n clearOrganizationReadModelsForRemoteReset,\n runOrganizationPresentationReset,\n} from \"../organizations/readModel/organizationRemoteReset\";\nimport {\n type RemoteResetInput,\n type RemoteSyncStateSnapshot,\n readRemoteSyncStateSnapshot,\n} from \"./remoteResetScope\";\n\nexport type {\n RemoteResetInput,\n RemoteResetReplacement,\n} from \"./remoteResetScope\";\n\nexport interface ClearRemoteSyncStateResult {\n readonly clearedContainerCreateIntentCount: number;\n readonly clearedContainerMoveIntentCount: number;\n readonly clearedDocumentMoveIntentCount: number;\n readonly clearedPrincipalPolicyCount: number;\n readonly clearedSyncCursorCount: number;\n readonly queuedAttachmentUploadCount: number;\n readonly queuedContainerCreateCount: number;\n readonly queuedDocumentUpdateCount: number;\n readonly resetContainerCount: number;\n readonly resetDocumentCount: number;\n}\n\n// Each subsystem resets its own tables; this runs their steps in one\n// transaction. Steps on different tables are independent, and each subsystem\n// clears its rows before it queues new ones.\nasync function clearRemoteSyncStateInTransaction(input: {\n plans: Awaited<ReturnType<typeof buildResetPlans>>;\n reset: RemoteResetInput;\n snapshot: RemoteSyncStateSnapshot;\n tx: ClientSQLiteTransactionScope;\n}): Promise<ClearRemoteSyncStateResult> {\n const now = new Date().toISOString();\n const { plans, reset, snapshot, tx } = input;\n const { organizationId } = reset;\n\n // Forget what the server told this device about the organization.\n await clearOrganizationReadModelsForRemoteReset(tx, organizationId);\n await clearDormantContainerMetadataForRemoteReset(tx, organizationId);\n await deleteVerifiedManifestBundlesForOrganization(tx, organizationId);\n await clearDocumentDiscoveryEvidenceOnRemoteReset(tx, {\n containerIds: snapshot.containerIds,\n documentIds: snapshot.oldDocumentIds,\n });\n await clearRemoteResetPrincipalRows({ organizationId, snapshot, tx });\n await clearContainerRowsForRemoteReset({\n containerIds: snapshot.containerIds,\n tx,\n });\n await clearDocumentPlacementsForRemoteReset({\n documentLocalIds: snapshot.documentLocalIds,\n oldDocumentIds: snapshot.oldDocumentIds,\n tx,\n });\n await clearDocumentRowsForRemoteReset({\n attachmentUploads: plans.attachmentUploads,\n documentLocalIds: snapshot.documentLocalIds,\n documentRows: snapshot.documentRows,\n tx,\n });\n await clearRemoteResetSyncCursors({\n containerIds: snapshot.containerIds,\n tx,\n });\n\n // Strip server identity from the rows the device keeps.\n await resetDocumentServerIdentity({\n documentLocalIds: snapshot.documentLocalIds,\n documentRows: snapshot.documentRows,\n now,\n organizationId: reset.replacement?.organizationId ?? organizationId,\n tx,\n });\n await resetContainerServerIdentity({\n containerIds: snapshot.containerIds,\n containerRows: snapshot.containerRows,\n now,\n reset,\n tx,\n });\n\n // Queue the local content to be published again.\n await queueDocumentRepublishForRemoteReset({\n documentUpdates: plans.documentUpdates,\n now,\n tx,\n });\n const queuedContainerCreateCount = await queueContainerCreatesForRemoteReset({\n containerRows: snapshot.containerRows,\n now,\n reset,\n tx,\n });\n await queueAttachmentReuploadsForRemoteReset({\n attachmentUploads: plans.attachmentUploads,\n now,\n tx,\n });\n return {\n clearedContainerCreateIntentCount:\n snapshot.clearedContainerCreateIntentCount,\n clearedContainerMoveIntentCount: snapshot.clearedContainerMoveIntentCount,\n clearedDocumentMoveIntentCount: snapshot.clearedDocumentMoveIntentCount,\n clearedPrincipalPolicyCount: snapshot.clearedPrincipalPolicyCount,\n clearedSyncCursorCount: snapshot.clearedSyncCursorCount,\n queuedAttachmentUploadCount: plans.attachmentUploads.length,\n queuedContainerCreateCount,\n queuedDocumentUpdateCount: plans.documentUpdates.length,\n resetContainerCount: snapshot.containerRows.length,\n resetDocumentCount: snapshot.documentRows.length,\n };\n}\n\nexport async function clearRemoteSyncState(\n execSql: ExecSql,\n reset: RemoteResetInput,\n canCommit?: (() => boolean) | undefined,\n): Promise<ClearRemoteSyncStateResult> {\n return runOrganizationPresentationReset(\n execSql,\n reset.organizationId,\n async () => {\n await ensureSqlTables(execSql, clientSqlTables);\n const runtime = getClientSQLitePersistenceRuntime(execSql);\n const resetInTransaction = async (tx: ClientSQLiteTransactionScope) => {\n if (canCommit && !canCommit()) {\n throw new Error(\n \"Remote sync reset aborted: session identity changed\",\n );\n }\n const snapshot = await readRemoteSyncStateSnapshot(\n tx,\n reset.organizationId,\n );\n const plans = await buildResetPlans(tx, snapshot.documentRows);\n return clearRemoteSyncStateInTransaction({\n plans,\n reset,\n snapshot,\n tx,\n });\n };\n if (!canCommit) {\n return runtime.transaction(resetInTransaction);\n }\n const outcome = await runtime.guardedTransaction(\n resetInTransaction,\n canCommit,\n );\n if (!outcome.committed || !outcome.result) {\n throw new Error(\"Remote sync reset aborted: session identity changed\");\n }\n return outcome.result;\n },\n );\n}\n"]}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import { type RemoteResetPrincipalKey } from "../../data/persistence/principalPolicy/principalPolicyRemoteReset.js";
|
|
1
2
|
import type { ClientSQLiteTransactionScope } from "../../data/sqlite/sqlitePersistenceRuntime.js";
|
|
2
|
-
import type
|
|
3
|
-
import { type
|
|
3
|
+
import { type ResetContainerRow } from "../container-contents/remoteReset/containerRemoteReset.js";
|
|
4
|
+
import { type ResetDocumentRow } from "../documents/remoteReset/documentRemoteReset.js";
|
|
4
5
|
export interface RemoteResetReplacement {
|
|
5
6
|
readonly organizationId: string;
|
|
6
7
|
readonly rootContainerId: string;
|
|
@@ -9,14 +10,6 @@ export interface RemoteResetInput {
|
|
|
9
10
|
readonly organizationId: string;
|
|
10
11
|
readonly replacement?: RemoteResetReplacement | undefined;
|
|
11
12
|
}
|
|
12
|
-
export interface ResetContainerRow {
|
|
13
|
-
readonly id: string;
|
|
14
|
-
readonly parentId: string | null;
|
|
15
|
-
}
|
|
16
|
-
export interface ResetDocumentRow extends ResetDocumentScope {
|
|
17
|
-
readonly documentId: string | null;
|
|
18
|
-
readonly recoveryDocumentId: string | null;
|
|
19
|
-
}
|
|
20
13
|
export interface RemoteSyncStateSnapshot {
|
|
21
14
|
readonly clearedContainerCreateIntentCount: number;
|
|
22
15
|
readonly clearedContainerMoveIntentCount: number;
|
|
@@ -30,4 +23,8 @@ export interface RemoteSyncStateSnapshot {
|
|
|
30
23
|
readonly oldDocumentIds: readonly string[];
|
|
31
24
|
readonly principalKeys: readonly RemoteResetPrincipalKey[];
|
|
32
25
|
}
|
|
26
|
+
/**
|
|
27
|
+
* Reads what a reset of the organization covers, from each subsystem that owns
|
|
28
|
+
* part of it: folders, then the documents in them, then principal policies.
|
|
29
|
+
*/
|
|
33
30
|
export declare function readRemoteSyncStateSnapshot(tx: ClientSQLiteTransactionScope, organizationId: string): Promise<RemoteSyncStateSnapshot>;
|
|
@@ -1,121 +1,39 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { loadRemoteResetPrincipalScope, } from "./remoteResetPrincipalScope.js";
|
|
1
|
+
import { loadRemoteResetPrincipalScope, } from "../../data/persistence/principalPolicy/principalPolicyRemoteReset.js";
|
|
2
|
+
import { countContainerResetIntents, countRemoteResetSyncCursors, listDocumentPlacementRows, loadContainerResetScope, } from "../container-contents/remoteReset/containerRemoteReset.js";
|
|
3
|
+
import { loadDocumentResetScope, } from "../documents/remoteReset/documentRemoteReset.js";
|
|
5
4
|
function principalKeyOfRow(row) {
|
|
6
5
|
return `${row.principalType}\0${row.principalId}`;
|
|
7
6
|
}
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
const liveContainerRows = (await tx
|
|
13
|
-
.select({ id: containers.id, parentId: containers.parentId })
|
|
14
|
-
.from(containers)
|
|
15
|
-
.where(eq(containers.organizationId, organizationId))).flatMap((row) => (row.id ? [{ id: row.id, parentId: row.parentId }] : []));
|
|
16
|
-
const dormantContainerRows = await tx
|
|
17
|
-
.select({ id: dormantContainerMetadata.containerId })
|
|
18
|
-
.from(dormantContainerMetadata)
|
|
19
|
-
.where(eq(dormantContainerMetadata.organizationId, organizationId));
|
|
20
|
-
const containerRows = liveContainerRows;
|
|
21
|
-
return {
|
|
22
|
-
containerIds: [
|
|
23
|
-
...new Set([
|
|
24
|
-
...containerRows.map((row) => row.id),
|
|
25
|
-
...dormantContainerRows.map((row) => row.id),
|
|
26
|
-
]),
|
|
27
|
-
],
|
|
28
|
-
containerRows,
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
|
-
async function loadDocumentScope(input) {
|
|
32
|
-
const { organizationId, tx } = input;
|
|
33
|
-
const containerIdSet = new Set(input.containerIds);
|
|
34
|
-
const [allDocuments, projectionRows, linkRows] = await loadDocumentAssociationRows(tx);
|
|
35
|
-
const linkedDocumentIds = new Set(linkRows
|
|
36
|
-
.filter((row) => containerIdSet.has(row.containerId))
|
|
37
|
-
.map((row) => row.documentId));
|
|
38
|
-
const projectedLocalIds = new Set(projectionRows
|
|
39
|
-
.filter((row) => (row.containerId !== null && containerIdSet.has(row.containerId)) ||
|
|
40
|
-
row.organizationId === organizationId ||
|
|
41
|
-
(row.documentId !== null && linkedDocumentIds.has(row.documentId)))
|
|
42
|
-
.flatMap((row) => (row.localId ? [row.localId] : [])));
|
|
43
|
-
const documentRows = allDocuments.filter((row) => (row.appKind === "container-metadata" &&
|
|
44
|
-
containerIdSet.has(row.localId)) ||
|
|
45
|
-
(row.appKind === "documents" && projectedLocalIds.has(row.localId)) ||
|
|
46
|
-
(row.documentId !== null && linkedDocumentIds.has(row.documentId)));
|
|
47
|
-
return {
|
|
48
|
-
documentLocalIds: [
|
|
49
|
-
...new Set(documentRows
|
|
50
|
-
.filter((row) => row.appKind === "documents")
|
|
51
|
-
.map((row) => row.localId)),
|
|
52
|
-
],
|
|
53
|
-
documentRows,
|
|
54
|
-
oldDocumentIds: [
|
|
55
|
-
...new Set(documentRows.flatMap((row) => (row.documentId ? [row.documentId] : []))),
|
|
56
|
-
],
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
function loadDocumentAssociationRows(tx) {
|
|
60
|
-
return Promise.all([
|
|
61
|
-
tx
|
|
62
|
-
.select({
|
|
63
|
-
appKind: documents.appKind,
|
|
64
|
-
documentId: documents.documentId,
|
|
65
|
-
localId: documents.localId,
|
|
66
|
-
recoveryDocumentId: documents.recoveryDocumentId,
|
|
67
|
-
})
|
|
68
|
-
.from(documents),
|
|
69
|
-
tx.select().from(documentProjection),
|
|
70
|
-
tx.select().from(documentContainerProjection),
|
|
71
|
-
]);
|
|
72
|
-
}
|
|
73
|
-
async function loadSnapshotCounts(input) {
|
|
74
|
-
const { organizationId, tx } = input;
|
|
75
|
-
const containerIdSet = new Set(input.containerIds);
|
|
76
|
-
const documentScopeKeys = new Set(input.documentRows.map(scopeKey));
|
|
77
|
-
const [principalScope, intents] = await Promise.all([
|
|
78
|
-
loadRemoteResetPrincipalScope(tx, organizationId),
|
|
79
|
-
tx
|
|
80
|
-
.select({
|
|
81
|
-
lane: localIntents.lane,
|
|
82
|
-
localId: localIntents.localId,
|
|
83
|
-
subjectId: localIntents.subjectId,
|
|
84
|
-
})
|
|
85
|
-
.from(localIntents),
|
|
86
|
-
]);
|
|
87
|
-
const containerIntentCount = (lane) => intents.filter((row) => row.lane === lane && containerIdSet.has(row.subjectId)).length;
|
|
88
|
-
const principalKeys = principalScope.principalKeys;
|
|
89
|
-
const principalKeySet = new Set(principalKeys.map(principalKeyOfRow));
|
|
90
|
-
const scopedContainerIds = new Set(input.containerIds);
|
|
91
|
-
const syncLanes = await tx.select().from(containerSyncWatermarks);
|
|
92
|
-
return {
|
|
93
|
-
clearedContainerCreateIntentCount: containerIntentCount(LOCAL_INTENT_LANES.containerCreate),
|
|
94
|
-
clearedContainerMoveIntentCount: containerIntentCount(LOCAL_INTENT_LANES.containerMove),
|
|
95
|
-
clearedDocumentMoveIntentCount: intents.filter((row) => row.lane === LOCAL_INTENT_LANES.documentPlacement &&
|
|
96
|
-
row.localId !== null &&
|
|
97
|
-
documentScopeKeys.has(scopeKey({ appKind: "documents", localId: row.localId }))).length,
|
|
98
|
-
clearedPrincipalPolicyCount: principalScope.policyRows.filter((row) => principalKeySet.has(`${row.type}\0${row.id}`)).length,
|
|
99
|
-
clearedSyncCursorCount: syncLanes.filter((row) => isRemoteResetSyncCursor({
|
|
100
|
-
containerIds: scopedContainerIds,
|
|
101
|
-
row,
|
|
102
|
-
})).length,
|
|
103
|
-
principalKeys,
|
|
104
|
-
};
|
|
105
|
-
}
|
|
7
|
+
/**
|
|
8
|
+
* Reads what a reset of the organization covers, from each subsystem that owns
|
|
9
|
+
* part of it: folders, then the documents in them, then principal policies.
|
|
10
|
+
*/
|
|
106
11
|
export async function readRemoteSyncStateSnapshot(tx, organizationId) {
|
|
107
|
-
const containerScope = await
|
|
108
|
-
const documentScope = await
|
|
12
|
+
const containerScope = await loadContainerResetScope(tx, organizationId);
|
|
13
|
+
const documentScope = await loadDocumentResetScope({
|
|
109
14
|
containerIds: containerScope.containerIds,
|
|
110
15
|
organizationId,
|
|
16
|
+
placementRows: await listDocumentPlacementRows(tx),
|
|
111
17
|
tx,
|
|
112
18
|
});
|
|
113
|
-
const
|
|
19
|
+
const principalScope = await loadRemoteResetPrincipalScope(tx, organizationId);
|
|
20
|
+
const intentCounts = await countContainerResetIntents({
|
|
114
21
|
containerIds: containerScope.containerIds,
|
|
115
|
-
|
|
116
|
-
organizationId,
|
|
22
|
+
documentLocalIds: documentScope.documentLocalIds,
|
|
117
23
|
tx,
|
|
118
24
|
});
|
|
119
|
-
|
|
25
|
+
const principalKeys = principalScope.principalKeys;
|
|
26
|
+
const principalKeySet = new Set(principalKeys.map(principalKeyOfRow));
|
|
27
|
+
return {
|
|
28
|
+
...containerScope,
|
|
29
|
+
...documentScope,
|
|
30
|
+
...intentCounts,
|
|
31
|
+
clearedPrincipalPolicyCount: principalScope.policyRows.filter((row) => principalKeySet.has(`${row.type}\0${row.id}`)).length,
|
|
32
|
+
clearedSyncCursorCount: await countRemoteResetSyncCursors({
|
|
33
|
+
containerIds: containerScope.containerIds,
|
|
34
|
+
tx,
|
|
35
|
+
}),
|
|
36
|
+
principalKeys,
|
|
37
|
+
};
|
|
120
38
|
}
|
|
121
39
|
//# sourceMappingURL=remoteResetScope.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"remoteResetScope.js","sourceRoot":"","sources":["remoteResetScope.ts"],"names":[],"mappings":"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","sourcesContent":["import { eq } from \"drizzle-orm\";\nimport {\n containerSyncWatermarks,\n containers,\n documentContainerProjection,\n documentProjection,\n documents,\n dormantContainerMetadata,\n LOCAL_INTENT_LANES,\n localIntents,\n} from \"../../data/sqlite/schema\";\nimport type { ClientSQLiteTransactionScope } from \"../../data/sqlite/sqlitePersistenceRuntime\";\nimport { isRemoteResetSyncCursor } from \"./remoteResetCursorScope\";\nimport type { ResetDocumentScope } from \"./remoteResetPlans\";\nimport {\n loadRemoteResetPrincipalScope,\n type RemoteResetPrincipalKey,\n} from \"./remoteResetPrincipalScope\";\n\nexport interface RemoteResetReplacement {\n readonly organizationId: string;\n readonly rootContainerId: string;\n}\n\nexport interface RemoteResetInput {\n readonly organizationId: string;\n readonly replacement?: RemoteResetReplacement | undefined;\n}\n\nexport interface ResetContainerRow {\n readonly id: string;\n readonly parentId: string | null;\n}\n\nexport interface ResetDocumentRow extends ResetDocumentScope {\n readonly documentId: string | null;\n readonly recoveryDocumentId: string | null;\n}\n\nexport interface RemoteSyncStateSnapshot {\n readonly clearedContainerCreateIntentCount: number;\n readonly clearedContainerMoveIntentCount: number;\n readonly clearedDocumentMoveIntentCount: number;\n readonly clearedPrincipalPolicyCount: number;\n readonly clearedSyncCursorCount: number;\n readonly containerIds: readonly string[];\n readonly containerRows: readonly ResetContainerRow[];\n readonly documentLocalIds: readonly string[];\n readonly documentRows: readonly ResetDocumentRow[];\n readonly oldDocumentIds: readonly string[];\n readonly principalKeys: readonly RemoteResetPrincipalKey[];\n}\n\nfunction principalKeyOfRow(row: {\n readonly principalId: string;\n readonly principalType: string;\n}): string {\n return `${row.principalType}\\0${row.principalId}`;\n}\n\nfunction scopeKey(scope: ResetDocumentScope): string {\n return `${scope.appKind}\\0${scope.localId}`;\n}\n\nasync function loadContainerScope(\n tx: ClientSQLiteTransactionScope,\n organizationId: string,\n): Promise<{\n containerIds: string[];\n containerRows: ResetContainerRow[];\n}> {\n const liveContainerRows = (\n await tx\n .select({ id: containers.id, parentId: containers.parentId })\n .from(containers)\n .where(eq(containers.organizationId, organizationId))\n ).flatMap((row) => (row.id ? [{ id: row.id, parentId: row.parentId }] : []));\n const dormantContainerRows = await tx\n .select({ id: dormantContainerMetadata.containerId })\n .from(dormantContainerMetadata)\n .where(eq(dormantContainerMetadata.organizationId, organizationId));\n const containerRows = liveContainerRows;\n return {\n containerIds: [\n ...new Set([\n ...containerRows.map((row) => row.id),\n ...dormantContainerRows.map((row) => row.id),\n ]),\n ],\n containerRows,\n };\n}\n\nasync function loadDocumentScope(input: {\n containerIds: readonly string[];\n organizationId: string;\n tx: ClientSQLiteTransactionScope;\n}): Promise<{\n documentLocalIds: string[];\n documentRows: ResetDocumentRow[];\n oldDocumentIds: string[];\n}> {\n const { organizationId, tx } = input;\n const containerIdSet = new Set(input.containerIds);\n const [allDocuments, projectionRows, linkRows] =\n await loadDocumentAssociationRows(tx);\n const linkedDocumentIds = new Set(\n linkRows\n .filter((row) => containerIdSet.has(row.containerId))\n .map((row) => row.documentId),\n );\n const projectedLocalIds = new Set(\n projectionRows\n .filter(\n (row) =>\n (row.containerId !== null && containerIdSet.has(row.containerId)) ||\n row.organizationId === organizationId ||\n (row.documentId !== null && linkedDocumentIds.has(row.documentId)),\n )\n .flatMap((row) => (row.localId ? [row.localId] : [])),\n );\n const documentRows = allDocuments.filter(\n (row) =>\n (row.appKind === \"container-metadata\" &&\n containerIdSet.has(row.localId)) ||\n (row.appKind === \"documents\" && projectedLocalIds.has(row.localId)) ||\n (row.documentId !== null && linkedDocumentIds.has(row.documentId)),\n );\n return {\n documentLocalIds: [\n ...new Set(\n documentRows\n .filter((row) => row.appKind === \"documents\")\n .map((row) => row.localId),\n ),\n ],\n documentRows,\n oldDocumentIds: [\n ...new Set(\n documentRows.flatMap((row) => (row.documentId ? [row.documentId] : [])),\n ),\n ],\n };\n}\n\nfunction loadDocumentAssociationRows(tx: ClientSQLiteTransactionScope) {\n return Promise.all([\n tx\n .select({\n appKind: documents.appKind,\n documentId: documents.documentId,\n localId: documents.localId,\n recoveryDocumentId: documents.recoveryDocumentId,\n })\n .from(documents),\n tx.select().from(documentProjection),\n tx.select().from(documentContainerProjection),\n ]);\n}\n\nasync function loadSnapshotCounts(input: {\n containerIds: readonly string[];\n documentRows: readonly ResetDocumentRow[];\n organizationId: string;\n tx: ClientSQLiteTransactionScope;\n}) {\n const { organizationId, tx } = input;\n const containerIdSet = new Set(input.containerIds);\n const documentScopeKeys = new Set(input.documentRows.map(scopeKey));\n const [principalScope, intents] = await Promise.all([\n loadRemoteResetPrincipalScope(tx, organizationId),\n tx\n .select({\n lane: localIntents.lane,\n localId: localIntents.localId,\n subjectId: localIntents.subjectId,\n })\n .from(localIntents),\n ]);\n const containerIntentCount = (lane: string) =>\n intents.filter(\n (row) => row.lane === lane && containerIdSet.has(row.subjectId),\n ).length;\n const principalKeys = principalScope.principalKeys;\n const principalKeySet = new Set(principalKeys.map(principalKeyOfRow));\n const scopedContainerIds = new Set(input.containerIds);\n const syncLanes = await tx.select().from(containerSyncWatermarks);\n\n return {\n clearedContainerCreateIntentCount: containerIntentCount(\n LOCAL_INTENT_LANES.containerCreate,\n ),\n clearedContainerMoveIntentCount: containerIntentCount(\n LOCAL_INTENT_LANES.containerMove,\n ),\n clearedDocumentMoveIntentCount: intents.filter(\n (row) =>\n row.lane === LOCAL_INTENT_LANES.documentPlacement &&\n row.localId !== null &&\n documentScopeKeys.has(\n scopeKey({ appKind: \"documents\", localId: row.localId }),\n ),\n ).length,\n clearedPrincipalPolicyCount: principalScope.policyRows.filter((row) =>\n principalKeySet.has(`${row.type}\\0${row.id}`),\n ).length,\n clearedSyncCursorCount: syncLanes.filter((row) =>\n isRemoteResetSyncCursor({\n containerIds: scopedContainerIds,\n row,\n }),\n ).length,\n principalKeys,\n };\n}\n\nexport async function readRemoteSyncStateSnapshot(\n tx: ClientSQLiteTransactionScope,\n organizationId: string,\n): Promise<RemoteSyncStateSnapshot> {\n const containerScope = await loadContainerScope(tx, organizationId);\n const documentScope = await loadDocumentScope({\n containerIds: containerScope.containerIds,\n organizationId,\n tx,\n });\n const counts = await loadSnapshotCounts({\n containerIds: containerScope.containerIds,\n documentRows: documentScope.documentRows,\n organizationId,\n tx,\n });\n return { ...containerScope, ...documentScope, ...counts };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"remoteResetScope.js","sourceRoot":"","sources":["remoteResetScope.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,6BAA6B,GAE9B,MAAM,mEAAmE,CAAC;AAE3E,OAAO,EACL,0BAA0B,EAC1B,2BAA2B,EAC3B,yBAAyB,EACzB,uBAAuB,GAExB,MAAM,wDAAwD,CAAC;AAChE,OAAO,EACL,sBAAsB,GAEvB,MAAM,8CAA8C,CAAC;AA0BtD,SAAS,iBAAiB,CAAC,GAG1B;IACC,OAAO,GAAG,GAAG,CAAC,aAAa,KAAK,GAAG,CAAC,WAAW,EAAE,CAAC;AACpD,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,2BAA2B,CAC/C,EAAgC,EAChC,cAAsB;IAEtB,MAAM,cAAc,GAAG,MAAM,uBAAuB,CAAC,EAAE,EAAE,cAAc,CAAC,CAAC;IACzE,MAAM,aAAa,GAAG,MAAM,sBAAsB,CAAC;QACjD,YAAY,EAAE,cAAc,CAAC,YAAY;QACzC,cAAc;QACd,aAAa,EAAE,MAAM,yBAAyB,CAAC,EAAE,CAAC;QAClD,EAAE;KACH,CAAC,CAAC;IACH,MAAM,cAAc,GAAG,MAAM,6BAA6B,CACxD,EAAE,EACF,cAAc,CACf,CAAC;IACF,MAAM,YAAY,GAAG,MAAM,0BAA0B,CAAC;QACpD,YAAY,EAAE,cAAc,CAAC,YAAY;QACzC,gBAAgB,EAAE,aAAa,CAAC,gBAAgB;QAChD,EAAE;KACH,CAAC,CAAC;IACH,MAAM,aAAa,GAAG,cAAc,CAAC,aAAa,CAAC;IACnD,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC,aAAa,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC,CAAC;IACtE,OAAO;QACL,GAAG,cAAc;QACjB,GAAG,aAAa;QAChB,GAAG,YAAY;QACf,2BAA2B,EAAE,cAAc,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CACpE,eAAe,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,IAAI,KAAK,GAAG,CAAC,EAAE,EAAE,CAAC,CAC9C,CAAC,MAAM;QACR,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;YACxD,YAAY,EAAE,cAAc,CAAC,YAAY;YACzC,EAAE;SACH,CAAC;QACF,aAAa;KACd,CAAC;AACJ,CAAC","sourcesContent":["import {\n loadRemoteResetPrincipalScope,\n type RemoteResetPrincipalKey,\n} from \"../../data/persistence/principalPolicy/principalPolicyRemoteReset\";\nimport type { ClientSQLiteTransactionScope } from \"../../data/sqlite/sqlitePersistenceRuntime\";\nimport {\n countContainerResetIntents,\n countRemoteResetSyncCursors,\n listDocumentPlacementRows,\n loadContainerResetScope,\n type ResetContainerRow,\n} from \"../container-contents/remoteReset/containerRemoteReset\";\nimport {\n loadDocumentResetScope,\n type ResetDocumentRow,\n} from \"../documents/remoteReset/documentRemoteReset\";\n\nexport interface RemoteResetReplacement {\n readonly organizationId: string;\n readonly rootContainerId: string;\n}\n\nexport interface RemoteResetInput {\n readonly organizationId: string;\n readonly replacement?: RemoteResetReplacement | undefined;\n}\n\nexport interface RemoteSyncStateSnapshot {\n readonly clearedContainerCreateIntentCount: number;\n readonly clearedContainerMoveIntentCount: number;\n readonly clearedDocumentMoveIntentCount: number;\n readonly clearedPrincipalPolicyCount: number;\n readonly clearedSyncCursorCount: number;\n readonly containerIds: readonly string[];\n readonly containerRows: readonly ResetContainerRow[];\n readonly documentLocalIds: readonly string[];\n readonly documentRows: readonly ResetDocumentRow[];\n readonly oldDocumentIds: readonly string[];\n readonly principalKeys: readonly RemoteResetPrincipalKey[];\n}\n\nfunction principalKeyOfRow(row: {\n readonly principalId: string;\n readonly principalType: string;\n}): string {\n return `${row.principalType}\\0${row.principalId}`;\n}\n\n/**\n * Reads what a reset of the organization covers, from each subsystem that owns\n * part of it: folders, then the documents in them, then principal policies.\n */\nexport async function readRemoteSyncStateSnapshot(\n tx: ClientSQLiteTransactionScope,\n organizationId: string,\n): Promise<RemoteSyncStateSnapshot> {\n const containerScope = await loadContainerResetScope(tx, organizationId);\n const documentScope = await loadDocumentResetScope({\n containerIds: containerScope.containerIds,\n organizationId,\n placementRows: await listDocumentPlacementRows(tx),\n tx,\n });\n const principalScope = await loadRemoteResetPrincipalScope(\n tx,\n organizationId,\n );\n const intentCounts = await countContainerResetIntents({\n containerIds: containerScope.containerIds,\n documentLocalIds: documentScope.documentLocalIds,\n tx,\n });\n const principalKeys = principalScope.principalKeys;\n const principalKeySet = new Set(principalKeys.map(principalKeyOfRow));\n return {\n ...containerScope,\n ...documentScope,\n ...intentCounts,\n clearedPrincipalPolicyCount: principalScope.policyRows.filter((row) =>\n principalKeySet.has(`${row.type}\\0${row.id}`),\n ).length,\n clearedSyncCursorCount: await countRemoteResetSyncCursors({\n containerIds: containerScope.containerIds,\n tx,\n }),\n principalKeys,\n };\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"organizationAccessRestoration.js","sourceRoot":"","sources":["organizationAccessRestoration.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gCAAgC,EAAE,MAAM,yEAAyE,CAAC;AAC3H,OAAO,EAAE,uCAAuC,EAAE,MAAM,gEAAgE,CAAC;AAEzH,OAAO,EAAE,+BAA+B,EAAE,MAAM,uCAAuC,CAAC;AACxF,OAAO,EACL,yBAAyB,EACzB,qBAAqB,GACtB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,gCAAgC,EAAE,MAAM,6CAA6C,CAAC;AAG/F,2EAA2E;AAC3E,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAAC,KAI/C;IACC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,GAAG,KAAK,CAAC;IACpD,IAAI,CAAC,YAAY,EAAE;QAAE,OAAO;IAC5B,iEAAiE;IACjE,mEAAmE;IACnE,iEAAiE;IACjE,sEAAsE;IACtE,oEAAoE;IACpE,gCAAgC;IAChC,IACE,CAAC,CAAC,MAAM,+BAA+B,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACpE,CAAC,MAAM,gCAAgC,CAAC,oBAAoB,CAC1D,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,EAC5B,EAAE,cAAc,EAAE,MAAM,CAAC,cAAc,EAAE,CAC1C,CAAC,CAAC;QACL,YAAY,EAAE,EACd,CAAC;QACD,kEAAkE;QAClE,4DAA4D;QAC5D,MAAM,gCAAgC,CAAC,sBAAsB,CAC3D,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,EAC5B,EAAE,cAAc,EAAE,MAAM,CAAC,cAAc,EAAE,CAC1C,CAAC;QACF,IAAI,YAAY,EAAE;YAAE,yBAAyB,CAAC,WAAW,CAAC,CAAC;IAC7D,CAAC;IACD,sEAAsE;IACtE,+DAA+D;IAC/D,6DAA6D;IAC7D,IAAI,YAAY,EAAE,EAAE,CAAC;QACnB,MAAM,0BAA0B,GAC9B,MAAM,uCAAuC,CAC3C,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,EAC5B;YACE,eAAe,EAAE,MAAM,CAAC,MAAM;SAC/B,CACF,CAAC;QACJ,IAAI,0BAA0B,GAAG,CAAC,IAAI,YAAY,EAAE,EAAE,CAAC;YACrD,qBAAqB,CAAC,WAAW,EAAE,gCAAgC,CAAC,CAAC;QACvE,CAAC;IACH,CAAC;AACH,CAAC","sourcesContent":["import { sqlDocumentMoveIntentPersistence } from \"../../data/persistence/container-contents/documentMoveIntentPersistence\";\nimport { requestDormantMetadataRestorationSweeps } from \"../../data/persistence/container-contents/dormantMetadataSweep\";\nimport type { DomainScope } from \"../../data/shared/domainScope\";\nimport { hasRecordedTerminalSyncFailures } from \"../../data/sqlite/documentPersistence\";\nimport {\n requestAllDomainSyncLanes,\n requestDomainSyncLane,\n} from \"../../data/sync/syncCoordinator\";\nimport { CONTAINER_CONTENTS_SYNC_LANE_KEY } from \"../../workflows/container-contents/syncLane\";\nimport type { ActiveOrganizationDataRuntime } from \"./organizationWorkflowRuntime\";\n\n/** Recover parked work before optional presentation hydration can fail. */\nexport async function recoverOrganizationAccess(input: {\n readonly active: ActiveOrganizationDataRuntime;\n readonly domainScope: DomainScope;\n readonly stillCurrent: () => boolean;\n}): Promise<void> {\n const { active, domainScope, stillCurrent } = input;\n if (!stillCurrent()) return;\n // The evidence gate: re-arm only when some queued write actually\n // recorded a terminal failure. A transient denial during bootstrap\n // (e.g. a read-model 403 before grants propagate) also flips the\n // denied flag, and re-arming then would race the startup sync passes.\n // A failed pass (`undefined`) proves nothing about restored access,\n // so it must not re-arm either.\n if (\n ((await hasRecordedTerminalSyncFailures(active.runtime.infra.execSql)) ||\n (await sqlDocumentMoveIntentPersistence.hasDeniedMoveIntents(\n active.runtime.infra.execSql,\n { organizationId: active.organizationId },\n ))) &&\n stillCurrent()\n ) {\n // Parked permission-denied moves (row 7) only replay once flipped\n // back to pending; restore them before re-arming the lanes.\n await sqlDocumentMoveIntentPersistence.resetDeniedMoveIntents(\n active.runtime.infra.execSql,\n { organizationId: active.organizationId },\n );\n if (stillCurrent()) requestAllDomainSyncLanes(domainScope);\n }\n // Keep dormant cleanup independent from the write-lane evidence gate,\n // but run it afterward so a SQLite failure cannot suppress the\n // pre-existing denied-write and move-intent recovery signal.\n if (stillCurrent()) {\n const requestedDormantSweepCount =\n await requestDormantMetadataRestorationSweeps(\n active.runtime.infra.execSql,\n {\n requesterUserId: active.userId,\n },\n );\n if (requestedDormantSweepCount > 0 && stillCurrent()) {\n requestDomainSyncLane(domainScope, CONTAINER_CONTENTS_SYNC_LANE_KEY);\n }\n }\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"documentHistoryPersistence.js","sourceRoot":"","sources":["documentHistoryPersistence.ts"],"names":[],"mappings":"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","sourcesContent":["import { base64ToBytes } from \"@tearleads/encoding\";\nimport {\n createDocument,\n exportFullHistoryIdentity,\n importSnapshot,\n satisfiesVersionVector,\n} from \"@tearleads/loro\";\nimport { and, eq, inArray, isNull, ne, sql } from \"drizzle-orm\";\nimport {\n documentHistoryCheckpoints,\n documentHistoryUpdates,\n documentTables,\n} from \"../schema\";\nimport { getClientSQLitePersistenceRuntime } from \"../sqlitePersistenceRuntime\";\nimport { type ExecSql, ensureSqlTables } from \"../sqlSchema\";\nimport type { DocumentScope } from \"./documentPersistenceTypes\";\n\n/**\n * Compaction thresholds: once the tail carries this many rows or bytes, the\n * next persist of a full-history-capable document exports a fresh checkpoint\n * and clears the tail. Small enough to keep restore replay short, large\n * enough that a full-history export (O(history)) happens once per burst of\n * edits instead of per keystroke.\n */\nexport const DOCUMENT_HISTORY_COMPACTION_MAX_ROWS = 200;\nexport const DOCUMENT_HISTORY_COMPACTION_MAX_BYTES = 512 * 1024;\n\n/**\n * Row provenance: \"local\" for updates authored on this device, \"remote\" for\n * decrypted pulled updates. Restores advance the outgoing-delta marker across\n * remote rows (already server-side); local rows never advance it.\n */\ntype DocumentHistoryUpdateOrigin = \"local\" | \"remote\";\n\n/**\n * Rows of the update log that are history tail: every row except an \"outbox\"\n * row, which only waits to be sent (see `documentHistoryUpdates`).\n */\nfunction tailInScope(scope: DocumentScope) {\n return and(\n eq(documentHistoryUpdates.appKind, scope.appKind),\n eq(documentHistoryUpdates.localId, scope.localId),\n ne(documentHistoryUpdates.origin, \"outbox\"),\n );\n}\n\n/**\n * Tail rows compaction may fold into a checkpoint and delete: a queued row is\n * the only durable copy of an unsent update, so it waits for settlement even\n * when a checkpoint already covers its operations.\n */\nfunction compactableTailInScope(scope: DocumentScope) {\n return and(tailInScope(scope), isNull(documentHistoryUpdates.updateId));\n}\n\ninterface DocumentHistoryTailUpdate {\n readonly origin: DocumentHistoryUpdateOrigin;\n readonly updateData: string;\n}\n\ninterface DocumentHistoryRestoreState {\n readonly snapshot: string;\n readonly tailUpdates: readonly DocumentHistoryTailUpdate[];\n}\n\nexport async function appendDocumentHistoryUpdates(\n execSql: ExecSql,\n scope: DocumentScope,\n updates: readonly string[],\n origin: DocumentHistoryUpdateOrigin,\n): Promise<void> {\n if (updates.length === 0) {\n return;\n }\n await ensureSqlTables(execSql, documentTables);\n const createdAt = new Date().toISOString();\n await getClientSQLitePersistenceRuntime(execSql).runMutation(async (db) => {\n // Chunked: a catch-up pull can carry thousands of updates, and a single\n // multi-row insert would exceed SQLite's bound-variable limit.\n for (let index = 0; index < updates.length; index += HISTORY_ROW_CHUNK) {\n await db.insert(documentHistoryUpdates).values(\n updates.slice(index, index + HISTORY_ROW_CHUNK).map((updateData) => ({\n id: crypto.randomUUID(),\n appKind: scope.appKind,\n localId: scope.localId,\n updateData,\n origin,\n createdAt,\n })),\n );\n }\n });\n}\n\n/**\n * The checkpoint + ordered tail for a scope, or null when NEITHER exists (a\n * discovered shell that has not hydrated content yet; the caller starts the\n * document empty and the remote pull supplies the content). A tail WITHOUT a\n * checkpoint — a crash between the first enqueued edit's tail append and the\n * birth-checkpoint seed — restores as tail-only (`snapshot: \"\"`): those tail\n * rows can be the only durable copy of a local edit, so they must never be\n * silently ignored.\n */\nexport async function loadDocumentHistoryRestoreState(\n execSql: ExecSql,\n scope: DocumentScope,\n): Promise<DocumentHistoryRestoreState | null> {\n await ensureSqlTables(execSql, documentTables);\n const { db } = getClientSQLitePersistenceRuntime(execSql);\n // Read the TAIL before the (full) checkpoint: if another pane compacts\n // between the two reads, this order yields old-tail + new-checkpoint — a\n // safe superset (the new checkpoint subsumes the old tail, and replay is\n // idempotent by op identity). The reverse order could yield old-checkpoint\n // + already-emptied tail, a torn read that silently drops the compacted\n // ops for the whole session.\n const tail = await db\n .select({\n id: documentHistoryUpdates.id,\n origin: documentHistoryUpdates.origin,\n updateData: documentHistoryUpdates.updateData,\n })\n .from(documentHistoryUpdates)\n .where(tailInScope(scope))\n // Insertion order: same-millisecond appends make createdAt tie and a\n // random-uuid tiebreak would replay out of order. importUpdates tolerates\n // out-of-order batches, but replay should still be deterministic.\n .orderBy(sql`rowid`);\n\n const [checkpoint] = await db\n .select({ snapshot: documentHistoryCheckpoints.snapshot })\n .from(documentHistoryCheckpoints)\n .where(\n and(\n eq(documentHistoryCheckpoints.appKind, scope.appKind),\n eq(documentHistoryCheckpoints.localId, scope.localId),\n ),\n )\n .limit(1);\n if (!checkpoint && tail.length === 0) {\n return null;\n }\n\n return {\n snapshot: checkpoint?.snapshot ?? \"\",\n tailUpdates: tail.map((row) => ({\n // Fail toward re-sending: an unrecognized origin never advances the\n // marker, which is the recoverable direction (a redundant re-submit\n // is idempotent; a skipped local op would be orphaned from sync).\n origin:\n row.origin === \"remote\" ? (\"remote\" as const) : (\"local\" as const),\n updateData: row.updateData,\n })),\n };\n}\n\n/**\n * Size of the tail compaction can shrink. Queued rows are excluded: they stay\n * until settlement, so counting them would re-export full history on every\n * persist while offline edits wait to sync.\n */\nexport async function readDocumentHistoryTailSize(\n execSql: ExecSql,\n scope: DocumentScope,\n): Promise<{ byteLength: number; hasCheckpoint: boolean; rowCount: number }> {\n await ensureSqlTables(execSql, documentTables);\n const { db } = getClientSQLitePersistenceRuntime(execSql);\n const [totals] = await db\n .select({\n byteLength: sql<number>`coalesce(sum(length(${documentHistoryUpdates.updateData})), 0)`,\n rowCount: sql<number>`count(*)`,\n })\n .from(documentHistoryUpdates)\n .where(compactableTailInScope(scope));\n const [checkpoint] = await db\n .select({ localId: documentHistoryCheckpoints.localId })\n .from(documentHistoryCheckpoints)\n .where(\n and(\n eq(documentHistoryCheckpoints.appKind, scope.appKind),\n eq(documentHistoryCheckpoints.localId, scope.localId),\n ),\n )\n .limit(1);\n return {\n byteLength: Number(totals?.byteLength ?? 0),\n hasCheckpoint: checkpoint !== undefined,\n rowCount: Number(totals?.rowCount ?? 0),\n };\n}\n\ninterface DocumentHistoryTailEntry {\n readonly id: string;\n readonly updateData: string;\n}\n\n/**\n * The current compactable tail rows WITH their payloads, so a compactor can\n * prove each row's ops are covered by the snapshot it is about to install\n * (another pane's append may carry ops this pane's document has not merged\n * yet). Queued rows are never candidates.\n */\nexport async function listDocumentHistoryTailEntries(\n execSql: ExecSql,\n scope: DocumentScope,\n): Promise<DocumentHistoryTailEntry[]> {\n await ensureSqlTables(execSql, documentTables);\n const { db } = getClientSQLitePersistenceRuntime(execSql);\n const rows = await db\n .select({\n id: documentHistoryUpdates.id,\n updateData: documentHistoryUpdates.updateData,\n })\n .from(documentHistoryUpdates)\n .where(compactableTailInScope(scope));\n return rows.flatMap((row) =>\n row.id === null ? [] : [{ id: row.id, updateData: row.updateData }],\n );\n}\n\nconst HISTORY_ROW_CHUNK = 400;\n\n/**\n * Replace the scope's checkpoint with a fresh full-history snapshot and\n * delete ONLY the tail rows the caller captured before exporting it. Every\n * append path writes its tail row after the ops are already in the live\n * document, so any row captured before the export is provably covered by\n * the snapshot — while a row appended concurrently (between export and this\n * delete) survives for the next compaction instead of being lost.\n */\nexport async function replaceDocumentHistoryCheckpoint(\n execSql: ExecSql,\n scope: DocumentScope,\n input: {\n coveredTailIds: readonly string[];\n endVersionVector: string;\n /**\n * Skip the monotonic version gate. Only for document CREATION, where any\n * existing checkpoint under this localId is the orphan of a failed prior\n * attempt (checkpoint written, record row never committed) — a retry's\n * fresh document need not dominate that orphan to replace it.\n */\n force?: boolean;\n snapshot: string;\n /**\n * Re-checked after acquiring the serialized mutation slot (like the\n * record-save path): a store reset/recreation that happened while this\n * call waited in the queue must abort the write, or a stale compactor\n * could install the OLD document's checkpoint over the new identity's.\n */\n stillCurrent?: () => boolean;\n },\n): Promise<boolean> {\n await ensureSqlTables(execSql, documentTables);\n // Sequential (non-transactional) so callers already inside a transaction\n // can nest this. Crash between the statements leaves the new checkpoint\n // plus covered tail rows — a safe superset, since tail replay is\n // idempotent by op identity. The replacement itself is a compare-and-swap\n // on the stored revision, so the version gate cannot be bypassed by a\n // concurrent compactor between the read and the write: whoever loses the\n // CAS re-reads and re-evaluates the gate against the winner's checkpoint.\n return getClientSQLitePersistenceRuntime(execSql).runMutation(async (tx) => {\n if (input.stillCurrent?.() === false) {\n return false;\n }\n for (let attempt = 0; attempt < CHECKPOINT_CAS_ATTEMPTS; attempt += 1) {\n let replaced: boolean;\n try {\n replaced = await tryReplaceCheckpointOnce(tx, scope, input);\n } catch (error) {\n if (error instanceof CheckpointGateRejected) {\n // A fresher checkpoint dominates this candidate: no write, and\n // the caller's covered rows must stay for the covering pane.\n return false;\n }\n throw error;\n }\n if (!replaced) {\n // CAS lost to a concurrent writer — re-read and re-evaluate the\n // gate against the winner's checkpoint.\n continue;\n }\n for (\n let index = 0;\n index < input.coveredTailIds.length;\n index += HISTORY_ROW_CHUNK\n ) {\n // Never a queued row, even if a caller names one: its operations may\n // be in the checkpoint, but it is still the unsent update itself.\n await tx\n .delete(documentHistoryUpdates)\n .where(\n and(\n compactableTailInScope(scope),\n inArray(\n documentHistoryUpdates.id,\n input.coveredTailIds.slice(index, index + HISTORY_ROW_CHUNK),\n ),\n ),\n );\n }\n return true;\n }\n // Exhaustion must not read as durable success: creation and rebuild\n // callers persist record rows assuming the checkpoint landed.\n throw new Error(\n \"Document history checkpoint replacement lost every CAS attempt\",\n );\n });\n}\n\nconst CHECKPOINT_CAS_ATTEMPTS = 16;\n\ntype MutationDb = Parameters<\n Parameters<\n ReturnType<typeof getClientSQLitePersistenceRuntime>[\"runMutation\"]\n >[0]\n>[0];\n\n/**\n * One compare-and-swap attempt. Returns true when this caller's checkpoint\n * became the stored one, false when a concurrent writer won the CAS (the\n * caller re-reads and retries), and throws CheckpointGateRejected when a\n * fresher stored checkpoint dominates the candidate.\n */\nasync function tryReplaceCheckpointOnce(\n tx: MutationDb,\n scope: DocumentScope,\n input: {\n endVersionVector: string;\n force?: boolean;\n snapshot: string;\n },\n): Promise<boolean> {\n const updatedAt = new Date().toISOString();\n const revision = crypto.randomUUID();\n const [stored] = await tx\n .select({\n endVersionVector: documentHistoryCheckpoints.endVersionVector,\n revision: documentHistoryCheckpoints.revision,\n snapshot: documentHistoryCheckpoints.snapshot,\n })\n .from(documentHistoryCheckpoints)\n .where(\n and(\n eq(documentHistoryCheckpoints.appKind, scope.appKind),\n eq(documentHistoryCheckpoints.localId, scope.localId),\n ),\n )\n .limit(1);\n\n if (!stored) {\n const inserted = await tx\n .insert(documentHistoryCheckpoints)\n .values({\n appKind: scope.appKind,\n localId: scope.localId,\n snapshot: input.snapshot,\n endVersionVector: input.endVersionVector,\n revision,\n updatedAt,\n })\n .onConflictDoNothing({\n target: [\n documentHistoryCheckpoints.appKind,\n documentHistoryCheckpoints.localId,\n ],\n })\n .returning({ localId: documentHistoryCheckpoints.localId });\n // Conflict means a concurrent writer inserted first — retry the gate.\n return inserted.length > 0;\n }\n\n // A stale compactor (a pane whose document has not merged another pane's\n // ops) must never replace a checkpoint it does not cover: the covered\n // pane may already have deleted its tail rows, so regressing the\n // checkpoint would leave those ops with no durable copy at all. Vector\n // dominance proves counter coverage; the retained-prefix identity also\n // proves the candidate carries the exact stored operations at those\n // counters rather than a same-frontier fork.\n if (input.force !== true) {\n if (\n !satisfiesVersionVector(input.endVersionVector, stored.endVersionVector)\n ) {\n throw new CheckpointGateRejected();\n }\n if (\n input.snapshot !== stored.snapshot &&\n !(await candidateContainsStoredCheckpointHistory({\n candidateSnapshot: input.snapshot,\n storedEndVersion: stored.endVersionVector,\n storedSnapshot: stored.snapshot,\n }))\n ) {\n throw new CheckpointGateRejected();\n }\n }\n\n const replaced = await tx\n .update(documentHistoryCheckpoints)\n .set({\n snapshot: input.snapshot,\n endVersionVector: input.endVersionVector,\n revision,\n updatedAt,\n })\n .where(\n and(\n eq(documentHistoryCheckpoints.appKind, scope.appKind),\n eq(documentHistoryCheckpoints.localId, scope.localId),\n eq(documentHistoryCheckpoints.revision, stored.revision),\n ),\n )\n .returning({ localId: documentHistoryCheckpoints.localId });\n return replaced.length > 0;\n}\n\nasync function candidateContainsStoredCheckpointHistory(input: {\n candidateSnapshot: string;\n storedEndVersion: string;\n storedSnapshot: string;\n}): Promise<boolean> {\n const [candidateDocument, storedDocument] = await Promise.all([\n createDocument(\"checkpoint-candidate-history-gate\"),\n createDocument(\"checkpoint-stored-history-gate\"),\n ]);\n try {\n importSnapshot(candidateDocument, base64ToBytes(input.candidateSnapshot));\n importSnapshot(storedDocument, base64ToBytes(input.storedSnapshot));\n return (\n exportFullHistoryIdentity(candidateDocument, input.storedEndVersion) ===\n exportFullHistoryIdentity(storedDocument)\n );\n } finally {\n candidateDocument.free();\n storedDocument.free();\n }\n}\n\nclass CheckpointGateRejected extends Error {\n constructor() {\n super(\"checkpoint gate rejected\");\n this.name = \"CheckpointGateRejected\";\n }\n}\n\nexport async function deleteDocumentHistory(\n execSql: ExecSql,\n scope: DocumentScope,\n): Promise<void> {\n await ensureSqlTables(execSql, documentTables);\n await getClientSQLitePersistenceRuntime(execSql).runMutation(async (tx) => {\n await tx\n .delete(documentHistoryCheckpoints)\n .where(\n and(\n eq(documentHistoryCheckpoints.appKind, scope.appKind),\n eq(documentHistoryCheckpoints.localId, scope.localId),\n ),\n );\n await tx\n .delete(documentHistoryUpdates)\n .where(\n and(\n eq(documentHistoryUpdates.appKind, scope.appKind),\n eq(documentHistoryUpdates.localId, scope.localId),\n ),\n );\n });\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"documentOrphanBlobReclaims.js","sourceRoot":"","sources":["documentOrphanBlobReclaims.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAEzD,iFAAiF;AACjF,MAAM,CAAC,MAAM,0BAA0B,GAAG,WAAW,CACnD,+BAA+B,EAC/B,EAAE,UAAU,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC,UAAU,EAAE,EAAE,CACjD,CAAC;AAEF,MAAM,CAAC,MAAM,8BAA8B,GAAG,oBAAoB,CAChE,0BAA0B,CAC3B,CAAC","sourcesContent":["import { sqliteTable, text } from \"drizzle-orm/sqlite-core\";\nimport { defineSqlTableSchema } from \"../sqlTableSchema\";\n\n/** Durable byte-reclamation queue populated before orphan attachment rows go. */\nexport const documentOrphanBlobReclaims = sqliteTable(\n \"document_orphan_blob_reclaims\",\n { storageKey: text(\"storage_key\").primaryKey() },\n);\n\nexport const documentOrphanBlobReclaimTable = defineSqlTableSchema(\n documentOrphanBlobReclaims,\n);\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"documentPendingUpdatePersistence.js","sourceRoot":"","sources":["documentPendingUpdatePersistence.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,GAAG,EACH,GAAG,EACH,EAAE,EACF,OAAO,EACP,SAAS,EACT,EAAE,EACF,EAAE,EAEF,GAAG,GACJ,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,sBAAsB,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAE9D,OAAO,EAAE,iCAAiC,EAAE,MAAM,6BAA6B,CAAC;AAShF;;;;;GAKG;AACH,MAAM,aAAa,GAAG,QAAQ,CAAC;AAK/B,SAAS,aAAa,CAAC,KAAoB;IACzC,OAAO,GAAG,CACR,EAAE,CAAC,sBAAsB,CAAC,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,EACjD,EAAE,CAAC,sBAAsB,CAAC,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,EACjD,SAAS,CAAC,sBAAsB,CAAC,QAAQ,CAAC,CAC3C,CAAC;AACJ,CAAC;AAED,SAAS,wBAAwB,CAC/B,GAA6B;IAE7B,yEAAyE;IACzE,0EAA0E;IAC1E,IACE,GAAG,CAAC,yBAAyB,KAAK,IAAI;QACtC,GAAG,CAAC,uBAAuB,KAAK,IAAI,EACpC,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,uDAAuD,CAAC,CAAC;IAC3E,CAAC;IACD,OAAO;QACL,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,CAAC;QACxB,UAAU,EAAE,GAAG,CAAC,UAAU;QAC1B,yBAAyB,EAAE,GAAG,CAAC,yBAAyB;QACxD,uBAAuB,EAAE,GAAG,CAAC,uBAAuB;QACpD,mBAAmB,EAAE,GAAG,CAAC,mBAAmB;QAC5C,UAAU,EAAE,GAAG,CAAC,UAAU;KAC3B,CAAC;AACJ,CAAC;AAED,+EAA+E;AAC/E,MAAM,CAAC,KAAK,UAAU,6BAA6B,CACjD,EAAa,EACb,OAAe,EACf,QAA2B;IAE3B,MAAM,SAAS,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC;IACzC,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IACtC,MAAM,IAAI,GAAG,MAAM,EAAE;SAClB,cAAc,CAAC,EAAE,OAAO,EAAE,sBAAsB,CAAC,OAAO,EAAE,CAAC;SAC3D,IAAI,CAAC,sBAAsB,CAAC;SAC5B,KAAK,CACJ,GAAG,CACD,EAAE,CAAC,sBAAsB,CAAC,OAAO,EAAE,OAAO,CAAC,EAC3C,OAAO,CAAC,sBAAsB,CAAC,OAAO,EAAE,SAAS,CAAC,EAClD,SAAS,CAAC,sBAAsB,CAAC,QAAQ,CAAC,CAC3C,CACF;SACA,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,OAAO,CAAC,CAAC,CAAC;IAChD,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AACxC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC5C,EAAa,EACb,KAAoB;IAEpB,MAAM,GAAG,GAAG,MAAM,6BAA6B,CAAC,EAAE,EAAE,KAAK,CAAC,OAAO,EAAE;QACjE,KAAK,CAAC,OAAO;KACd,CAAC,CAAC;IACH,OAAO,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC;AACxB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,0BAA0B,CAC9C,OAAgB,EAChB,KAAoB;IAEpB,MAAM,EAAE,EAAE,EAAE,GAAG,iCAAiC,CAAC,OAAO,CAAC,CAAC;IAC1D,MAAM,IAAI,GAAG,MAAM,EAAE;SAClB,MAAM,CAAC;QACN,EAAE,EAAE,sBAAsB,CAAC,QAAQ;QACnC,UAAU,EAAE,sBAAsB,CAAC,UAAU;QAC7C,yBAAyB,EACvB,sBAAsB,CAAC,yBAAyB;QAClD,uBAAuB,EAAE,sBAAsB,CAAC,uBAAuB;QACvE,mBAAmB,EAAE,sBAAsB,CAAC,mBAAmB;QAC/D,UAAU,EAAE,sBAAsB,CAAC,UAAU;KAC9C,CAAC;SACD,IAAI,CAAC,sBAAsB,CAAC;SAC5B,KAAK,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;SAC3B,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,SAAS,CAAC,EAAE,GAAG,CAAC,GAAG,CAAA,OAAO,CAAC,CAAC,CAAC;IAEnE,OAAO,IAAI,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC;AAC5C,CAAC;AAED,uEAAuE;AACvE,MAAM,UAAU,eAAe,CAAC,KAM/B;IACC,OAAO;QACL,EAAE,EAAE,MAAM,CAAC,UAAU,EAAE;QACvB,OAAO,EAAE,KAAK,CAAC,KAAK,CAAC,OAAO;QAC5B,OAAO,EAAE,KAAK,CAAC,KAAK,CAAC,OAAO;QAC5B,UAAU,EAAE,KAAK,CAAC,aAAa,CAAC,UAAU;QAC1C,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,yBAAyB,EAAE,KAAK,CAAC,aAAa,CAAC,yBAAyB;QACxE,uBAAuB,EAAE,KAAK,CAAC,aAAa,CAAC,uBAAuB;QACpE,mBAAmB,EAAE,KAAK,CAAC,aAAa,CAAC,mBAAmB,IAAI,IAAI;KACrE,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,4BAA4B,CAChD,OAAgB,EAChB,KAAoB,EACpB,aAAkC;IAElC,MAAM,QAAQ,GAAG,MAAM,CAAC,UAAU,EAAE,CAAC;IACrC,MAAM,iCAAiC,CAAC,OAAO,CAAC,CAAC,WAAW,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE;QACxE,MAAM,EAAE;aACL,MAAM,CAAC,sBAAsB,CAAC;aAC9B,MAAM,CACL,eAAe,CAAC;YACd,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACnC,MAAM,EAAE,aAAa;YACrB,aAAa;YACb,KAAK;YACL,QAAQ;SACT,CAAC,CACH;aACA,GAAG,EAAE,CAAC;IACX,CAAC,CAAC,CAAC;IACH,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,uCAAuC,CAC3D,OAAgB,EAChB,KAAoB,EACpB,aAAkC,EAClC,OAGC;IAED,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC3C,OAAO,iCAAiC,CAAC,OAAO,CAAC,CAAC,WAAW,CAC3D,KAAK,EAAE,EAAE,EAAE,EAAE;QACX,IAAI,OAAO,EAAE,CAAC;YACZ,MAAM,iBAAiB,GAAG,MAAM,EAAE;iBAC/B,MAAM,CAAC,EAAE,OAAO,EAAE,SAAS,CAAC,OAAO,EAAE,CAAC;iBACtC,IAAI,CAAC,SAAS,CAAC;iBACf,KAAK,CACJ,GAAG,CACD,EAAE,CAAC,SAAS,CAAC,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,EACpC,EAAE,CAAC,SAAS,CAAC,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,EACpC,GAAG,CAAA,GAAG,SAAS,CAAC,UAAU,OAAO,OAAO,CAAC,kBAAkB,EAAE,EAC7D,EAAE,CACA,SAAS,CAAC,kBAAkB,EAC5B,OAAO,CAAC,0BAA0B,CACnC,CACF,CACF;iBACA,KAAK,CAAC,CAAC,CAAC,CAAC;YACZ,IAAI,iBAAiB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACnC,OAAO,IAAI,CAAC;YACd,CAAC;QACH,CAAC;QAED,OAAO,mDAAmD,CAAC;YACzD,SAAS;YACT,aAAa;YACb,KAAK;YACL,EAAE;SACH,CAAC,CAAC;IACL,CAAC,EACD,EAAE,QAAQ,EAAE,WAAW,EAAE,CAC1B,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,mDAAmD,CAAC,KAKzE;IACC,MAAM,QAAQ,GAAG,MAAM,CAAC,UAAU,EAAE,CAAC;IACrC,MAAM,KAAK,CAAC,EAAE;SACX,MAAM,CAAC,sBAAsB,CAAC;SAC9B,MAAM,CACL,eAAe,CAAC;QACd,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,MAAM,EAAE,OAAO;QACf,aAAa,EAAE,KAAK,CAAC,aAAa;QAClC,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,QAAQ;KACT,CAAC,CACH;SACA,GAAG,EAAE,CAAC;IACT,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,CAAC;AAE3C;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,qCAAqC,CACzD,OAAgB,EAChB,KAAoB;IAEpB,MAAM,iCAAiC,CAAC,OAAO,CAAC,CAAC,WAAW,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE;QACxE,MAAM,EAAE;aACL,MAAM,CAAC,sBAAsB,CAAC;aAC9B,GAAG,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,CAAC;aACtB,KAAK,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC;IACjC,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,0BAA0B,CAC9C,OAAgB,EAChB,EAAU;IAEV,MAAM,MAAM,GAAG,MAAM,CAAC,UAAU,EAAE,CAAC;IACnC,IAAI,OAAO,GAAG,KAAK,CAAC;IACpB,MAAM,iCAAiC,CAAC,OAAO,CAAC,CAAC,WAAW,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE;QACxE,MAAM,OAAO,GAAG,MAAM,EAAE;aACrB,MAAM,CAAC,sBAAsB,CAAC;aAC9B,GAAG,CAAC;YACH,QAAQ,EAAE,MAAM;YAChB,UAAU,EAAE,GAAG,CAAA,GAAG,sBAAsB,CAAC,UAAU,MAAM;SAC1D,CAAC;aACD,KAAK,CACJ,GAAG,CACD,EAAE,CAAC,sBAAsB,CAAC,QAAQ,EAAE,EAAE,CAAC,EACvC,EAAE,CAAC,sBAAsB,CAAC,UAAU,EAAE,yBAAyB,CAAC,CACjE,CACF;aACA,SAAS,CAAC,EAAE,EAAE,EAAE,sBAAsB,CAAC,QAAQ,EAAE,CAAC,CAAC;QACtD,OAAO,GAAG,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC;IAC/B,CAAC,CAAC,CAAC;IACH,OAAO,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;AACjC,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,wCAAwC,CAC5D,EAAkB,EAClB,KAAoB,EACpB,SAA4B;IAE5B,MAAM,SAAS,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC;IAC1C,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IACnC,MAAM,QAAQ,GAAG,GAAG,CAClB,EAAE,CAAC,sBAAsB,CAAC,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,EACjD,EAAE,CAAC,sBAAsB,CAAC,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,EACjD,OAAO,CAAC,sBAAsB,CAAC,QAAQ,EAAE,SAAS,CAAC,CACpD,CAAC;IACF,MAAM,sBAAsB,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC;AAC7C,CAAC;AAED,KAAK,UAAU,sBAAsB,CACnC,EAAkB,EAClB,QAAyB;IAEzB,MAAM,EAAE;SACL,MAAM,CAAC,sBAAsB,CAAC;SAC9B,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,CAAC,sBAAsB,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC,CAAC;SACtE,GAAG,EAAE,CAAC;IACT,MAAM,EAAE;SACL,MAAM,CAAC,sBAAsB,CAAC;SAC9B,GAAG,CAAC;QACH,QAAQ,EAAE,IAAI;QACd,yBAAyB,EAAE,IAAI;QAC/B,uBAAuB,EAAE,IAAI;QAC7B,mBAAmB,EAAE,IAAI;QACzB,UAAU,EAAE,CAAC;KACd,CAAC;SACD,KAAK,CAAC,QAAQ,CAAC;SACf,GAAG,EAAE,CAAC;AACX,CAAC;AAED,0DAA0D;AAC1D,MAAM,CAAC,KAAK,UAAU,2BAA2B,CAC/C,OAAgB,EAChB,EAAU;IAEV,MAAM,iCAAiC,CAAC,OAAO,CAAC,CAAC,WAAW,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE;QACxE,MAAM,sBAAsB,CAAC,EAAE,EAAE,EAAE,CAAC,sBAAsB,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,CAAC;IAC5E,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,kCAAkC,CACtD,EAAkB,EAClB,MAAgC;IAEhC,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IAChC,MAAM,sBAAsB,CAAC,EAAE,EAAE,EAAE,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;AACrE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,6BAA6B,CACjD,OAAgB,EAChB,KAAoB;IAEpB,MAAM,iCAAiC,CAAC,OAAO,CAAC,CAAC,WAAW,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE;QACxE,MAAM,kCAAkC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;IACxD,CAAC,CAAC,CAAC;AACL,CAAC","sourcesContent":["import {\n and,\n asc,\n eq,\n inArray,\n isNotNull,\n lt,\n or,\n type SQL,\n sql,\n} from \"drizzle-orm\";\nimport { documentHistoryUpdates, documents } from \"../schema\";\nimport type { ClientSQLiteTransactionScope } from \"../sqlitePersistenceRuntime\";\nimport { getClientSQLitePersistenceRuntime } from \"../sqlitePersistenceRuntime\";\nimport type { ExecSql } from \"../sqlSchema\";\nimport type {\n DocumentScope,\n PendingUpdateFields,\n PendingUpdateRecord,\n SelectedPendingUpdateRow,\n} from \"./documentPersistenceTypes\";\n\n/**\n * Queued updates are the rows of the local update log that carry an\n * `updateId`. A tail row (origin \"local\") stays in the log after settlement as\n * history until compaction; an \"outbox\" row has no tail role and settlement\n * deletes it.\n */\nconst OUTBOX_ORIGIN = \"outbox\";\n\ntype QueueStatement = Pick<ClientSQLiteTransactionScope, \"delete\" | \"update\">;\ntype QueueRead = Pick<ClientSQLiteTransactionScope, \"selectDistinct\">;\n\nfunction queuedInScope(scope: DocumentScope) {\n return and(\n eq(documentHistoryUpdates.appKind, scope.appKind),\n eq(documentHistoryUpdates.localId, scope.localId),\n isNotNull(documentHistoryUpdates.updateId),\n );\n}\n\nfunction mapSelectedPendingUpdate(\n row: SelectedPendingUpdateRow,\n): PendingUpdateRecord {\n // A queued row always carries its submission vectors; a row without them\n // cannot be submitted and must fail closed rather than send empty ranges.\n if (\n row.partialStartVersionVector === null ||\n row.partialEndVersionVector === null\n ) {\n throw new Error(\"Queued document update is missing its version vectors\");\n }\n return {\n id: String(row.id ?? \"\"),\n updateData: row.updateData,\n partialStartVersionVector: row.partialStartVersionVector,\n partialEndVersionVector: row.partialEndVersionVector,\n sourceVersionVector: row.sourceVersionVector,\n rekeyCount: row.rekeyCount,\n };\n}\n\n/** The ids among `localIds` (one app kind) with at least one queued update. */\nexport async function listLocalIdsWithQueuedUpdates(\n db: QueueRead,\n appKind: string,\n localIds: readonly string[],\n): Promise<string[]> {\n const uniqueIds = [...new Set(localIds)];\n if (uniqueIds.length === 0) return [];\n const rows = await db\n .selectDistinct({ localId: documentHistoryUpdates.localId })\n .from(documentHistoryUpdates)\n .where(\n and(\n eq(documentHistoryUpdates.appKind, appKind),\n inArray(documentHistoryUpdates.localId, uniqueIds),\n isNotNull(documentHistoryUpdates.updateId),\n ),\n )\n .orderBy(asc(documentHistoryUpdates.localId));\n return rows.map((row) => row.localId);\n}\n\nexport async function hasQueuedDocumentUpdates(\n db: QueueRead,\n scope: DocumentScope,\n): Promise<boolean> {\n const ids = await listLocalIdsWithQueuedUpdates(db, scope.appKind, [\n scope.localId,\n ]);\n return ids.length > 0;\n}\n\nexport async function listDocumentPendingUpdates(\n execSql: ExecSql,\n scope: DocumentScope,\n): Promise<PendingUpdateRecord[]> {\n const { db } = getClientSQLitePersistenceRuntime(execSql);\n const rows = await db\n .select({\n id: documentHistoryUpdates.updateId,\n updateData: documentHistoryUpdates.updateData,\n partialStartVersionVector:\n documentHistoryUpdates.partialStartVersionVector,\n partialEndVersionVector: documentHistoryUpdates.partialEndVersionVector,\n sourceVersionVector: documentHistoryUpdates.sourceVersionVector,\n rekeyCount: documentHistoryUpdates.rekeyCount,\n })\n .from(documentHistoryUpdates)\n .where(queuedInScope(scope))\n .orderBy(asc(documentHistoryUpdates.createdAt), asc(sql`rowid`));\n\n return rows.map(mapSelectedPendingUpdate);\n}\n\n/** One log row for a queued update; `origin` decides its tail role. */\nexport function queuedUpdateRow(input: {\n createdAt: string;\n origin: \"local\" | typeof OUTBOX_ORIGIN;\n pendingUpdate: PendingUpdateFields;\n scope: DocumentScope;\n updateId: string;\n}) {\n return {\n id: crypto.randomUUID(),\n appKind: input.scope.appKind,\n localId: input.scope.localId,\n updateData: input.pendingUpdate.updateData,\n origin: input.origin,\n createdAt: input.createdAt,\n updateId: input.updateId,\n partialStartVersionVector: input.pendingUpdate.partialStartVersionVector,\n partialEndVersionVector: input.pendingUpdate.partialEndVersionVector,\n sourceVersionVector: input.pendingUpdate.sourceVersionVector ?? null,\n };\n}\n\n/**\n * Queue an update that has no history-tail role: container metadata (its\n * content is its checkpoint) and full-state re-uploads after a remote reset.\n */\nexport async function enqueueDocumentPendingUpdate(\n execSql: ExecSql,\n scope: DocumentScope,\n pendingUpdate: PendingUpdateFields,\n): Promise<string> {\n const updateId = crypto.randomUUID();\n await getClientSQLitePersistenceRuntime(execSql).runMutation(async (db) => {\n await db\n .insert(documentHistoryUpdates)\n .values(\n queuedUpdateRow({\n createdAt: new Date().toISOString(),\n origin: OUTBOX_ORIGIN,\n pendingUpdate,\n scope,\n updateId,\n }),\n )\n .run();\n });\n return updateId;\n}\n\n/**\n * Append a locally authored update to the history tail AND queue it, as one\n * row in one transaction. A crash can therefore never leave the op restorable\n * from history while missing from the outgoing queue, where a null-marker\n * restore would classify it as covered and never send it.\n */\nexport async function enqueueDocumentPendingUpdateWithHistory(\n execSql: ExecSql,\n scope: DocumentScope,\n pendingUpdate: PendingUpdateFields,\n options?: {\n expectedDocumentId: string | null;\n expectedRecoveryGeneration: number;\n },\n): Promise<string | null> {\n const createdAt = new Date().toISOString();\n return getClientSQLitePersistenceRuntime(execSql).transaction(\n async (tx) => {\n if (options) {\n const matchingDocuments = await tx\n .select({ localId: documents.localId })\n .from(documents)\n .where(\n and(\n eq(documents.appKind, scope.appKind),\n eq(documents.localId, scope.localId),\n sql`${documents.documentId} IS ${options.expectedDocumentId}`,\n eq(\n documents.recoveryGeneration,\n options.expectedRecoveryGeneration,\n ),\n ),\n )\n .limit(1);\n if (matchingDocuments.length === 0) {\n return null;\n }\n }\n\n return insertDocumentPendingUpdateWithHistoryInTransaction({\n createdAt,\n pendingUpdate,\n scope,\n tx,\n });\n },\n { behavior: \"immediate\" },\n );\n}\n\nexport async function insertDocumentPendingUpdateWithHistoryInTransaction(input: {\n createdAt: string;\n pendingUpdate: PendingUpdateFields;\n scope: DocumentScope;\n tx: ClientSQLiteTransactionScope;\n}): Promise<string> {\n const updateId = crypto.randomUUID();\n await input.tx\n .insert(documentHistoryUpdates)\n .values(\n queuedUpdateRow({\n createdAt: input.createdAt,\n origin: \"local\",\n pendingUpdate: input.pendingUpdate,\n scope: input.scope,\n updateId,\n }),\n )\n .run();\n return updateId;\n}\n\n/**\n * Assign a fresh id to a queued update, keeping every other column. A lost\n * sync ack leaves the server holding the update under the original id with\n * ciphertext a rebuilt submission can never reproduce (each rebuild encrypts\n * with a fresh IV), so the id is permanently poisoned: every resubmission\n * 409s and the whole outgoing batch rolls back. Re-keying lets the next sync\n * pass submit the same ops under a conflict-free id; the server-side copy is\n * harmless because CRDT update import is idempotent.\n *\n * Returns null when no row carries the id, so callers never report progress\n * for a row that lives in some other queue (or nowhere). The UPDATE's own\n * RETURNING row is the progress signal — a pre-flight SELECT would race a\n * second tab sharing the SQLite file, which can settle the row between the\n * read and the write and turn \"rekeyed\" into a spurious re-arm.\n *\n * The persisted per-row bound is enforced here as well: a row already at\n * MAX_PENDING_UPDATE_REKEYS is left untouched and reported as no progress.\n * The in-memory lane counter bounds a busy-loop within one session; this\n * bound survives restarts, so a poisoned row cannot re-key forever at three\n * passes per launch.\n */\nexport const MAX_PENDING_UPDATE_REKEYS = 5;\n\n/**\n * Reset the durable re-key budget for every queued update in a scope. The\n * cap exists to stop a server that keeps conflicting fresh ids from driving\n * a network-speed loop — but a budget burned during an unrelated outage\n * (e.g. yesterday's stale-bundle deadlock 409ing every submit) should not be\n * terminal forever. An explicit manual retry is the deliberate, rate-limited\n * signal that conditions changed, so it gets a fresh budget.\n */\nexport async function resetDocumentPendingUpdateRekeyBudget(\n execSql: ExecSql,\n scope: DocumentScope,\n): Promise<void> {\n await getClientSQLitePersistenceRuntime(execSql).runMutation(async (db) => {\n await db\n .update(documentHistoryUpdates)\n .set({ rekeyCount: 0 })\n .where(queuedInScope(scope));\n });\n}\n\nexport async function rekeyDocumentPendingUpdate(\n execSql: ExecSql,\n id: string,\n): Promise<string | null> {\n const nextId = crypto.randomUUID();\n let rekeyed = false;\n await getClientSQLitePersistenceRuntime(execSql).runMutation(async (db) => {\n const updated = await db\n .update(documentHistoryUpdates)\n .set({\n updateId: nextId,\n rekeyCount: sql`${documentHistoryUpdates.rekeyCount} + 1`,\n })\n .where(\n and(\n eq(documentHistoryUpdates.updateId, id),\n lt(documentHistoryUpdates.rekeyCount, MAX_PENDING_UPDATE_REKEYS),\n ),\n )\n .returning({ id: documentHistoryUpdates.updateId });\n rekeyed = updated.length > 0;\n });\n return rekeyed ? nextId : null;\n}\n\n/**\n * Settle queued updates: an outbox row is deleted, and a tail row stops being\n * queued but stays as history until compaction folds it into a checkpoint.\n */\nexport async function settleQueuedDocumentUpdatesInTransaction(\n tx: QueueStatement,\n scope: DocumentScope,\n updateIds: readonly string[],\n): Promise<void> {\n const uniqueIds = [...new Set(updateIds)];\n if (uniqueIds.length === 0) return;\n const selected = and(\n eq(documentHistoryUpdates.appKind, scope.appKind),\n eq(documentHistoryUpdates.localId, scope.localId),\n inArray(documentHistoryUpdates.updateId, uniqueIds),\n );\n await unqueueSelectedUpdates(tx, selected);\n}\n\nasync function unqueueSelectedUpdates(\n tx: QueueStatement,\n selected: SQL | undefined,\n): Promise<void> {\n await tx\n .delete(documentHistoryUpdates)\n .where(and(selected, eq(documentHistoryUpdates.origin, OUTBOX_ORIGIN)))\n .run();\n await tx\n .update(documentHistoryUpdates)\n .set({\n updateId: null,\n partialStartVersionVector: null,\n partialEndVersionVector: null,\n sourceVersionVector: null,\n rekeyCount: 0,\n })\n .where(selected)\n .run();\n}\n\n/** Settle one queued update by id, whatever its scope. */\nexport async function settleDocumentPendingUpdate(\n execSql: ExecSql,\n id: string,\n): Promise<void> {\n await getClientSQLitePersistenceRuntime(execSql).runMutation(async (db) => {\n await unqueueSelectedUpdates(db, eq(documentHistoryUpdates.updateId, id));\n });\n}\n\n/**\n * Stop queueing every update in the given scopes: outbox rows are dropped,\n * and local tail rows keep their content as history (it is already in the\n * document).\n */\nexport async function unqueueDocumentScopesInTransaction(\n tx: QueueStatement,\n scopes: readonly DocumentScope[],\n): Promise<void> {\n if (scopes.length === 0) return;\n await unqueueSelectedUpdates(tx, or(...scopes.map(queuedInScope)));\n}\n\nexport async function unqueueDocumentPendingUpdates(\n execSql: ExecSql,\n scope: DocumentScope,\n): Promise<void> {\n await getClientSQLitePersistenceRuntime(execSql).runMutation(async (db) => {\n await unqueueDocumentScopesInTransaction(db, [scope]);\n });\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"documentPersistenceTypes.js","sourceRoot":"","sources":["documentPersistenceTypes.ts"],"names":[],"mappings":"","sourcesContent":["import type { ContainerAccessLevel } from \"@tearleads/crypto\";\nimport type { DocumentSyncPullContinuation } from \"../../documents/shared/sync/pullContinuation\";\n\nexport interface DocumentRecord {\n id: string;\n documentId: string | null;\n /**\n * Durable fence advanced by an atomic raw-history recovery install. Writers\n * capture this before waiting for the mutation queue and must refuse to\n * publish when recovery advanced it first.\n */\n recoveryGeneration?: number;\n /** Former server id reserved for deterministic post-purge recreation. */\n recoveryDocumentId?: string | null;\n /**\n * Encoded end version vector of the persisted content frontier. Content\n * itself lives in the durable history (checkpoint + tail); this column\n * exists so priming and coverage predicates can compare versions from a\n * narrow indexed column. Empty string means \"never hydrated\".\n */\n snapshotEndVersion: string;\n accessEpoch: number;\n accessStateHash?: string | null;\n effectiveAccessLevel?: ContainerAccessLevel | null;\n lastCommitLsn?: string | null;\n contentKeyBundle?: string | null;\n documentKekTargets?: string | null;\n documentManifestBundle?: string | null;\n pendingBaseVersion?: string | null;\n pullContinuation?: DocumentSyncPullContinuation | null;\n /**\n * The durable continuation column was non-null but could not be decoded.\n * Keep forcing a page-one pull until a successful settlement replaces the\n * malformed value; ordinary local saves must preserve that recovery signal.\n */\n pullContinuationRecoveryRequired?: true;\n}\n\nexport interface PendingUpdateFields {\n updateData: string;\n partialStartVersionVector: string;\n partialEndVersionVector: string;\n sourceVersionVector?: string | null;\n}\n\nexport interface PendingUpdateRecord extends PendingUpdateFields {\n id: string;\n /**\n * Times this row was assigned a fresh id by lost-ack conflict recovery.\n * Persisted so the bound survives restarts; absent means zero (rows from\n * simple test doubles).\n */\n rekeyCount?: number | undefined;\n}\n\nexport interface DocumentScope {\n appKind: string;\n localId: string;\n}\n\nexport interface SelectedDocumentRecordRow {\n id: string;\n documentId: string | null;\n recoveryGeneration: number;\n recoveryDocumentId: string | null;\n snapshotEndVersion: string;\n accessEpoch: number;\n accessStateHash: string | null;\n effectiveAccessLevel: string | null;\n lastCommitLsn: string | null;\n contentKeyBundle: string | null;\n documentKekTargets: string | null;\n documentManifestBundle: string | null;\n pendingBaseVersion: string | null;\n pullContinuation: string | null;\n}\n\nexport interface SelectedPendingUpdateRow {\n id: string | null;\n updateData: string;\n partialStartVersionVector: string | null;\n partialEndVersionVector: string | null;\n sourceVersionVector: string | null;\n rekeyCount: number;\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"documentRecordPersistence.js","sourceRoot":"","sources":["documentRecordPersistence.ts"],"names":[],"mappings":"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","sourcesContent":["import { and, desc, eq, sql } from \"drizzle-orm\";\nimport { deserializeDocumentSyncPullContinuation } from \"../../documents/shared/sync/pullContinuation\";\nimport { normalizeEffectiveAccessLevel } from \"../../keying/accessLevel\";\nimport { documentHistoryUpdates, documents } from \"../schema\";\nimport { getClientSQLitePersistenceRuntime } from \"../sqlitePersistenceRuntime\";\nimport type { ExecSql } from \"../sqlSchema\";\nimport type {\n DocumentRecord,\n DocumentScope,\n SelectedDocumentRecordRow,\n} from \"./documentPersistenceTypes\";\n\n/**\n * The ONE select shape for a full documents-row record: every reader that\n * feeds mapSelectedDocumentRecord spreads this, so a new record column cannot\n * silently miss one of them.\n */\nexport const documentRecordSelection = {\n id: documents.localId,\n documentId: documents.documentId,\n recoveryGeneration: documents.recoveryGeneration,\n recoveryDocumentId: documents.recoveryDocumentId,\n snapshotEndVersion: documents.snapshotEndVersion,\n accessEpoch: documents.accessEpoch,\n accessStateHash: documents.accessStateHash,\n effectiveAccessLevel: documents.effectiveAccessLevel,\n lastCommitLsn: documents.lastCommitLsn,\n documentManifestBundle: documents.documentManifestBundle,\n contentKeyBundle: documents.contentKeyBundle,\n documentKekTargets: documents.documentKekTargets,\n pendingBaseVersion: documents.pendingBaseVersion,\n pullContinuation: documents.pullContinuation,\n};\n\nexport function mapSelectedDocumentRecord(\n row: SelectedDocumentRecordRow,\n): DocumentRecord {\n const record: DocumentRecord = {\n id: row.id,\n documentId: row.documentId,\n recoveryGeneration: row.recoveryGeneration,\n snapshotEndVersion: row.snapshotEndVersion,\n accessEpoch: row.accessEpoch,\n effectiveAccessLevel: normalizeEffectiveAccessLevel(\n row.effectiveAccessLevel,\n ),\n lastCommitLsn: row.lastCommitLsn,\n contentKeyBundle: row.contentKeyBundle,\n documentKekTargets: row.documentKekTargets,\n documentManifestBundle: row.documentManifestBundle,\n };\n\n if (row.accessStateHash !== null) {\n record.accessStateHash = row.accessStateHash;\n }\n\n if (row.recoveryDocumentId !== null) {\n record.recoveryDocumentId = row.recoveryDocumentId;\n }\n\n // Only surface the marker when one was persisted, so a row that never stored\n // one keeps its prior shape (and init falls through to seeding it).\n if (row.pendingBaseVersion !== null) {\n record.pendingBaseVersion = row.pendingBaseVersion;\n }\n\n const pullContinuation = deserializeDocumentSyncPullContinuation(\n row.pullContinuation,\n );\n if (pullContinuation !== null) {\n record.pullContinuation = pullContinuation;\n } else if (row.pullContinuation !== null) {\n record.pullContinuationRecoveryRequired = true;\n }\n\n return record;\n}\n\nexport async function loadDocumentRecord(\n execSql: ExecSql,\n scope: DocumentScope,\n): Promise<DocumentRecord | null> {\n const { db } = getClientSQLitePersistenceRuntime(execSql);\n const rows = await db\n .select(documentRecordSelection)\n .from(documents)\n .where(\n and(\n eq(documents.appKind, scope.appKind),\n eq(documents.localId, scope.localId),\n ),\n )\n .limit(1);\n\n return rows[0] ? mapSelectedDocumentRecord(rows[0]) : null;\n}\n\nexport async function findLocalIdByDocumentId(\n execSql: ExecSql,\n appKind: string,\n documentId: string,\n): Promise<string | null> {\n const { db } = getClientSQLitePersistenceRuntime(execSql);\n const hasPendingUpdates = sql<number>`EXISTS (\n SELECT 1\n FROM ${documentHistoryUpdates}\n WHERE ${documentHistoryUpdates.appKind} = ${documents.appKind}\n AND ${documentHistoryUpdates.localId} = ${documents.localId}\n AND ${documentHistoryUpdates.updateId} IS NOT NULL\n )`;\n const hasPendingLocalWork = sql<number>`(\n ${hasPendingUpdates}\n OR (\n ${documents.pendingBaseVersion} IS NOT NULL\n AND ${documents.pendingBaseVersion} <> ${documents.snapshotEndVersion}\n )\n )`;\n const rows = await db\n .select({ localId: documents.localId })\n .from(documents)\n .where(\n and(eq(documents.appKind, appKind), eq(documents.documentId, documentId)),\n )\n // Duplicate remote identities can survive an interrupted local adoption.\n // Preserve queued or deferred edits, then make the fallback stable.\n .orderBy(\n desc(hasPendingLocalWork),\n desc(documents.updatedAt),\n desc(documents.localId),\n )\n .limit(1);\n\n return rows[0]?.localId ?? null;\n}\n\nexport async function deleteDocumentRecord(\n execSql: ExecSql,\n scope: DocumentScope,\n): Promise<void> {\n await getClientSQLitePersistenceRuntime(execSql).runMutation(async (db) => {\n await db\n .delete(documents)\n .where(\n and(\n eq(documents.appKind, scope.appKind),\n eq(documents.localId, scope.localId),\n ),\n )\n .run();\n });\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"documentSyncFailurePersistence.js","sourceRoot":"","sources":["documentSyncFailurePersistence.ts"],"names":[],"mappings":"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","sourcesContent":["import { and, eq, isNotNull } from \"drizzle-orm\";\nimport {\n documents,\n documentTables,\n localIntents,\n localIntentTables,\n} from \"../schema\";\nimport {\n type ClientSQLiteTransactionScope,\n getClientSQLitePersistenceRuntime,\n} from \"../sqlitePersistenceRuntime\";\nimport { type ExecSql, ensureSqlTables } from \"../sqlSchema\";\nimport type { DocumentScope } from \"./documentPersistenceTypes\";\n\ninterface DocumentSyncFailureFields {\n readonly attemptedAt: string;\n readonly message: string;\n readonly status: number | null;\n}\n\n/** The `documents` column values of a scope with no recorded failure. */\nexport const CLEARED_DOCUMENT_SYNC_FAILURE = {\n syncFailureAttemptedAt: null,\n syncFailureMessage: null,\n syncFailureStatus: null,\n} as const;\n\nfunction scopeWhere(scope: DocumentScope) {\n return and(\n eq(documents.appKind, scope.appKind),\n eq(documents.localId, scope.localId),\n );\n}\n\n/**\n * Record the last terminal failure or incoming-update quarantine on a document\n * scope's row. The durable pending-update queue has no status columns, so\n * these columns let the write-queue view explain a blocked document. A newer\n * failure replaces the old. A scope with no `documents` row has nothing left\n * to explain, so the update is a no-op there.\n */\nexport async function recordDocumentSyncFailure(\n execSql: ExecSql,\n scope: DocumentScope,\n failure: DocumentSyncFailureFields,\n): Promise<void> {\n await getClientSQLitePersistenceRuntime(execSql).runMutation(async (db) => {\n await db\n .update(documents)\n .set({\n syncFailureAttemptedAt: failure.attemptedAt,\n syncFailureMessage: failure.message,\n syncFailureStatus: failure.status,\n })\n .where(scopeWhere(scope))\n .run();\n });\n}\n\n/**\n * Whether any queued local write has recorded a terminal failure — a document\n * row carrying a sync failure or an intent row carrying `last_error`. This is\n * the evidence gate for recovery triggers (e.g. re-arming write lanes when org\n * access is restored): without it a transient denial during bootstrap would\n * fire recovery work with nothing to recover, racing the startup sync passes.\n */\nexport async function hasRecordedTerminalSyncFailures(\n execSql: ExecSql,\n): Promise<boolean> {\n await ensureSqlTables(execSql, [...documentTables, ...localIntentTables]);\n const { db } = getClientSQLitePersistenceRuntime(execSql);\n const [failure] = await db\n .select({ localId: documents.localId })\n .from(documents)\n .where(isNotNull(documents.syncFailureMessage))\n .limit(1);\n if (failure) {\n return true;\n }\n const [intent] = await db\n .select({ id: localIntents.id })\n .from(localIntents)\n .where(isNotNull(localIntents.lastError))\n .limit(1);\n return intent !== undefined;\n}\n\n/** Clear a scope's recorded failure inside a caller's transaction. */\nexport async function clearDocumentSyncFailureInTransaction(\n tx: ClientSQLiteTransactionScope,\n scope: DocumentScope,\n): Promise<void> {\n await tx\n .update(documents)\n .set(CLEARED_DOCUMENT_SYNC_FAILURE)\n .where(scopeWhere(scope))\n .run();\n}\n\n/**\n * Drop the recorded failure for a scope. Called when a later sync pass for the\n * scope succeeds and whenever the scope's local sync state is torn down, so a\n * stale failure never outlives the condition it describes.\n */\nexport async function clearDocumentSyncFailure(\n execSql: ExecSql,\n scope: DocumentScope,\n): Promise<void> {\n await getClientSQLitePersistenceRuntime(execSql).runMutation(async (db) => {\n await db\n .update(documents)\n .set(CLEARED_DOCUMENT_SYNC_FAILURE)\n .where(scopeWhere(scope))\n .run();\n });\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"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","sourcesContent":["import { and, eq, sql } from \"drizzle-orm\";\nimport {\n DOCUMENT_SYNC_PULL_RECOVERY_REQUIRED,\n type DocumentSyncPullContinuation,\n serializeDocumentSyncPullContinuation,\n} from \"../../documents/shared/sync/pullContinuation\";\nimport { documentProjectionTables, documents, documentTables } from \"../schema\";\nimport { getClientSQLitePersistenceRuntime } from \"../sqlitePersistenceRuntime\";\nimport {\n type ExecSql,\n ensureSqlTables,\n runSerializedSqlMutation,\n} from \"../sqlSchema\";\nimport type { DocumentRecord } from \"./documentPersistenceTypes\";\nimport { loadDocumentRecord } from \"./documentRecordPersistence\";\n\nexport function ensureDocumentTables(execSql: ExecSql): Promise<void> {\n return ensureSqlTables(execSql, documentTables);\n}\n\nexport function ensureDocumentProjectionTables(\n execSql: ExecSql,\n): Promise<void> {\n return ensureSqlTables(execSql, documentProjectionTables);\n}\n\n/** Replace only the exact rejected continuation with a durable recovery marker. */\nexport async function invalidateDocumentSyncPullContinuation(\n execSql: ExecSql,\n input: {\n accessEpoch: number;\n accessStateHash: string | null;\n appKind: string;\n continuation: DocumentSyncPullContinuation;\n contentKeyBundle: string | null;\n documentId: string;\n documentKekTargets: string | null;\n documentManifestBundle: string | null;\n lastCommitLsn: string | null;\n localId: string;\n },\n): Promise<DocumentRecord | null> {\n await ensureDocumentTables(execSql);\n const expectedContinuation = serializeDocumentSyncPullContinuation(\n input.continuation,\n );\n if (expectedContinuation === null) return null;\n return runSerializedSqlMutation(execSql, async (lockedExecSql) => {\n const { db } = getClientSQLitePersistenceRuntime(lockedExecSql);\n await db\n .update(documents)\n .set({ pullContinuation: DOCUMENT_SYNC_PULL_RECOVERY_REQUIRED })\n .where(\n and(\n eq(documents.appKind, input.appKind),\n eq(documents.localId, input.localId),\n eq(documents.documentId, input.documentId),\n eq(documents.accessEpoch, input.accessEpoch),\n sql`${documents.accessStateHash} IS ${input.accessStateHash}`,\n sql`${documents.contentKeyBundle} IS ${input.contentKeyBundle}`,\n sql`${documents.documentKekTargets} IS ${input.documentKekTargets}`,\n sql`${documents.documentManifestBundle} IS ${input.documentManifestBundle}`,\n sql`${documents.lastCommitLsn} IS ${input.lastCommitLsn}`,\n eq(documents.pullContinuation, expectedContinuation),\n ),\n )\n .run();\n return loadDocumentRecord(lockedExecSql, {\n appKind: input.appKind,\n localId: input.localId,\n });\n });\n}\n\nexport {\n enqueueDocumentPendingUpdate,\n enqueueDocumentPendingUpdateWithHistory,\n listDocumentPendingUpdates,\n MAX_PENDING_UPDATE_REKEYS,\n rekeyDocumentPendingUpdate,\n resetDocumentPendingUpdateRekeyBudget,\n settleDocumentPendingUpdate,\n unqueueDocumentPendingUpdates,\n} from \"./documentPendingUpdatePersistence\";\nexport type {\n DocumentRecord,\n DocumentScope,\n PendingUpdateFields,\n PendingUpdateRecord,\n} from \"./documentPersistenceTypes\";\nexport {\n deleteDocumentRecord,\n documentRecordSelection,\n findLocalIdByDocumentId,\n loadDocumentRecord,\n mapSelectedDocumentRecord,\n} from \"./documentRecordPersistence\";\nexport {\n clearDocumentSyncFailure,\n hasRecordedTerminalSyncFailures,\n recordDocumentSyncFailure,\n} from \"./documentSyncFailurePersistence\";\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"remoteResetAttachments.js","sourceRoot":"","sources":["remoteResetAttachments.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AACtC,OAAO,EAAE,kCAAkC,EAAE,MAAM,0DAA0D,CAAC;AAC9G,OAAO,EAAE,0BAA0B,EAAE,MAAM,0BAA0B,CAAC;AAEtE,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAG1D,+EAA+E;AAC/E,MAAM,CAAC,KAAK,UAAU,4BAA4B,CAAC,KAIlD;IACC,MAAM,YAAY,GAAG,IAAI,GAAG,CAC1B,KAAK,CAAC,iBAAiB,CAAC,GAAG,CACzB,CAAC,UAAU,EAAE,EAAE,CAAC,GAAG,UAAU,CAAC,OAAO,KAAK,UAAU,CAAC,MAAM,EAAE,CAC9D,CACF,CAAC;IACF,KAAK,MAAM,YAAY,IAAI,kBAAkB,CAAC,KAAK,CAAC,gBAAgB,CAAC,EAAE,CAAC;QACtE,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,EAAE;aACxB,MAAM,CAAC;YACN,OAAO,EAAE,0BAA0B,CAAC,OAAO;YAC3C,MAAM,EAAE,0BAA0B,CAAC,MAAM;YACzC,UAAU,EAAE,0BAA0B,CAAC,UAAU;SAClD,CAAC;aACD,IAAI,CAAC,0BAA0B,CAAC;aAChC,KAAK,CAAC,OAAO,CAAC,0BAA0B,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC;QACpE,MAAM,kCAAkC,CACtC,KAAK,CAAC,EAAE,EACR,IAAI;aACD,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,OAAO,KAAK,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;aACnE,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,CAChC,CAAC;QACF,MAAM,KAAK,CAAC,EAAE;aACX,MAAM,CAAC,0BAA0B,CAAC;aAClC,KAAK,CAAC,OAAO,CAAC,0BAA0B,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;aAChE,GAAG,EAAE,CAAC;IACX,CAAC;AACH,CAAC","sourcesContent":["import { inArray } from \"drizzle-orm\";\nimport { queueDocumentAttachmentStorageKeys } from \"../../data/persistence/documents/internal/orphanSideRows\";\nimport { documentPendingAttachments } from \"../../data/sqlite/schema\";\nimport type { ClientSQLiteTransactionScope } from \"../../data/sqlite/sqlitePersistenceRuntime\";\nimport { remoteResetBatches } from \"./remoteResetBatches\";\nimport type { ResetAttachmentUpload } from \"./remoteResetPlans\";\n\n/** Delete reset-scoped pending rows without abandoning dropped local bytes. */\nexport async function clearResetPendingAttachments(input: {\n readonly attachmentUploads: readonly ResetAttachmentUpload[];\n readonly documentLocalIds: readonly string[];\n readonly tx: ClientSQLiteTransactionScope;\n}): Promise<void> {\n const requeuedKeys = new Set(\n input.attachmentUploads.map(\n (attachment) => `${attachment.localId}\\0${attachment.slotId}`,\n ),\n );\n for (const localIdBatch of remoteResetBatches(input.documentLocalIds)) {\n const rows = await input.tx\n .select({\n localId: documentPendingAttachments.localId,\n slotId: documentPendingAttachments.slotId,\n storageKey: documentPendingAttachments.storageKey,\n })\n .from(documentPendingAttachments)\n .where(inArray(documentPendingAttachments.localId, localIdBatch));\n await queueDocumentAttachmentStorageKeys(\n input.tx,\n rows\n .filter((row) => !requeuedKeys.has(`${row.localId}\\0${row.slotId}`))\n .map((row) => row.storageKey),\n );\n await input.tx\n .delete(documentPendingAttachments)\n .where(inArray(documentPendingAttachments.localId, localIdBatch))\n .run();\n }\n}\n"]}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
// Keep bulk inserts, IN predicates, and expanded pair predicates comfortably
|
|
2
|
-
// below SQLite's common 999-bind and expression-depth limits. Some queued rows
|
|
3
|
-
// consume more than ten binds each, so one conservative size covers every
|
|
4
|
-
// reset statement.
|
|
5
|
-
export const REMOTE_RESET_SQL_BATCH_SIZE = 50;
|
|
6
|
-
export function remoteResetBatches(values) {
|
|
7
|
-
const batches = [];
|
|
8
|
-
for (let offset = 0; offset < values.length; offset += REMOTE_RESET_SQL_BATCH_SIZE) {
|
|
9
|
-
batches.push(values.slice(offset, offset + REMOTE_RESET_SQL_BATCH_SIZE));
|
|
10
|
-
}
|
|
11
|
-
return batches;
|
|
12
|
-
}
|
|
13
|
-
//# sourceMappingURL=remoteResetBatches.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"remoteResetBatches.js","sourceRoot":"","sources":["remoteResetBatches.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,+EAA+E;AAC/E,0EAA0E;AAC1E,mBAAmB;AACnB,MAAM,CAAC,MAAM,2BAA2B,GAAG,EAAE,CAAC;AAE9C,MAAM,UAAU,kBAAkB,CAChC,MAAoB;IAEpB,MAAM,OAAO,GAAU,EAAE,CAAC;IAC1B,KACE,IAAI,MAAM,GAAG,CAAC,EACd,MAAM,GAAG,MAAM,CAAC,MAAM,EACtB,MAAM,IAAI,2BAA2B,EACrC,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,2BAA2B,CAAC,CAAC,CAAC;IAC3E,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC","sourcesContent":["// Keep bulk inserts, IN predicates, and expanded pair predicates comfortably\n// below SQLite's common 999-bind and expression-depth limits. Some queued rows\n// consume more than ten binds each, so one conservative size covers every\n// reset statement.\nexport const REMOTE_RESET_SQL_BATCH_SIZE = 50;\n\nexport function remoteResetBatches<T>(\n values: readonly T[],\n): readonly (readonly T[])[] {\n const batches: T[][] = [];\n for (\n let offset = 0;\n offset < values.length;\n offset += REMOTE_RESET_SQL_BATCH_SIZE\n ) {\n batches.push(values.slice(offset, offset + REMOTE_RESET_SQL_BATCH_SIZE));\n }\n return batches;\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"remoteResetCursorScope.js","sourceRoot":"","sources":["remoteResetCursorScope.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AAEnE,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAE1D,MAAM,wBAAwB,GAAG,qBAAqB,CAAC;AACvD,MAAM,qBAAqB,GAAG,kBAAkB,CAAC;AACjD,6EAA6E;AAC7E,0EAA0E;AAC1E,MAAM,YAAY,GAAG,MAAM,CAAC;AAC5B,MAAM,kBAAkB,GAAG,SAAS,CAAC;AAOrC,MAAM,UAAU,uBAAuB,CAAC,KAGvC;IACC,IAAI,KAAK,CAAC,GAAG,CAAC,QAAQ,KAAK,wBAAwB,EAAE,CAAC;QACpD,OAAO,KAAK,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAClD,CAAC;IACD,IAAI,KAAK,CAAC,GAAG,CAAC,QAAQ,KAAK,qBAAqB;QAAE,OAAO,KAAK,CAAC;IAC/D,IAAI,KAAK,CAAC,GAAG,CAAC,MAAM,KAAK,YAAY;QAAE,OAAO,IAAI,CAAC;IACnD,OAAO,CACL,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,kBAAkB,CAAC;QAC/C,KAAK,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,kBAAkB,CAAC,MAAM,CAAC,CAAC,CAC1E,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,2BAA2B,CAAC,KAGjD;IACC,mEAAmE;IACnE,MAAM,KAAK,GAAG,uBAAuB,CAAC;IACtC,MAAM,KAAK,CAAC,EAAE;SACX,MAAM,CAAC,KAAK,CAAC;SACb,KAAK,CACJ,GAAG,CACD,EAAE,CAAC,KAAK,CAAC,QAAQ,EAAE,qBAAqB,CAAC,EACzC,EAAE,CAAC,KAAK,CAAC,MAAM,EAAE,YAAY,CAAC,CAC/B,CACF;SACA,GAAG,EAAE,CAAC;IACT,KAAK,MAAM,cAAc,IAAI,kBAAkB,CAAC,KAAK,CAAC,YAAY,CAAC,EAAE,CAAC;QACpE,MAAM,aAAa,GAAG,cAAc,CAAC,GAAG,CACtC,CAAC,WAAW,EAAE,EAAE,CAAC,GAAG,kBAAkB,GAAG,WAAW,EAAE,CACvD,CAAC;QACF,MAAM,KAAK,CAAC,EAAE;aACX,MAAM,CAAC,KAAK,CAAC;aACb,KAAK,CACJ,EAAE,CACA,GAAG,CACD,EAAE,CAAC,KAAK,CAAC,QAAQ,EAAE,qBAAqB,CAAC,EACzC,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,aAAa,CAAC,CACrC,EACD,GAAG,CACD,EAAE,CAAC,KAAK,CAAC,QAAQ,EAAE,wBAAwB,CAAC,EAC5C,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,cAAc,CAAC,CACtC,CACF,CACF;aACA,GAAG,EAAE,CAAC;IACX,CAAC;AACH,CAAC","sourcesContent":["import { and, eq, inArray, or } from \"drizzle-orm\";\nimport { containerSyncWatermarks } from \"../../data/sqlite/schema\";\nimport type { ClientSQLiteTransactionScope } from \"../../data/sqlite/sqlitePersistenceRuntime\";\nimport { remoteResetBatches } from \"./remoteResetBatches\";\n\nconst CONTAINER_DOCUMENTS_LANE = \"container_documents\";\nconst CONTAINER_PARENT_LANE = \"container_parent\";\n// The API root feed lists every accessible organization. Its one cursor must\n// reset on any organization's purge; child feeds use globally unique IDs.\nconst ROOT_LANE_ID = \"root\";\nconst PARENT_LANE_PREFIX = \"parent:\";\n\ninterface SyncCursorRow {\n readonly laneId: string;\n readonly laneKind: string;\n}\n\nexport function isRemoteResetSyncCursor(input: {\n containerIds: ReadonlySet<string>;\n row: SyncCursorRow;\n}): boolean {\n if (input.row.laneKind === CONTAINER_DOCUMENTS_LANE) {\n return input.containerIds.has(input.row.laneId);\n }\n if (input.row.laneKind !== CONTAINER_PARENT_LANE) return false;\n if (input.row.laneId === ROOT_LANE_ID) return true;\n return (\n input.row.laneId.startsWith(PARENT_LANE_PREFIX) &&\n input.containerIds.has(input.row.laneId.slice(PARENT_LANE_PREFIX.length))\n );\n}\n\nexport async function clearRemoteResetSyncCursors(input: {\n containerIds: readonly string[];\n tx: ClientSQLiteTransactionScope;\n}): Promise<void> {\n // One row per lane holds both the cursor and its freshness marker.\n const table = containerSyncWatermarks;\n await input.tx\n .delete(table)\n .where(\n and(\n eq(table.laneKind, CONTAINER_PARENT_LANE),\n eq(table.laneId, ROOT_LANE_ID),\n ),\n )\n .run();\n for (const containerBatch of remoteResetBatches(input.containerIds)) {\n const parentLaneIds = containerBatch.map(\n (containerId) => `${PARENT_LANE_PREFIX}${containerId}`,\n );\n await input.tx\n .delete(table)\n .where(\n or(\n and(\n eq(table.laneKind, CONTAINER_PARENT_LANE),\n inArray(table.laneId, parentLaneIds),\n ),\n and(\n eq(table.laneKind, CONTAINER_DOCUMENTS_LANE),\n inArray(table.laneId, containerBatch),\n ),\n ),\n )\n .run();\n }\n}\n"]}
|