@itwin/core-backend 4.0.0-dev.41 → 4.0.0-dev.46
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/lib/cjs/CheckpointManager.d.ts.map +1 -1
- package/lib/cjs/CheckpointManager.js +3 -0
- package/lib/cjs/CheckpointManager.js.map +1 -1
- package/lib/cjs/CloudSqlite.d.ts +15 -10
- package/lib/cjs/CloudSqlite.d.ts.map +1 -1
- package/lib/cjs/CloudSqlite.js +1 -0
- package/lib/cjs/CloudSqlite.js.map +1 -1
- package/package.json +12 -12
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CheckpointManager.d.ts","sourceRoot":"","sources":["../../src/CheckpointManager.ts"],"names":[],"mappings":"AAIA;;GAEG;AAKH,OAAO,EAAE,OAAO,EAAyB,UAAU,
|
|
1
|
+
{"version":3,"file":"CheckpointManager.d.ts","sourceRoot":"","sources":["../../src/CheckpointManager.ts"],"names":[],"mappings":"AAIA;;GAEG;AAKH,OAAO,EAAE,OAAO,EAAyB,UAAU,EAAgE,MAAM,qBAAqB,CAAC;AAC/I,OAAO,EACa,WAAW,EAAE,oBAAoB,EAAmD,YAAY,EAAE,aAAa,EAClI,MAAM,oBAAoB,CAAC;AAI5B,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAOlD;;;GAGG;AACH,MAAM,WAAW,eAAgB,SAAQ,QAAQ;IAC/C,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAE5B,uCAAuC;IACvC,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC;IAE7B,uBAAuB;IACvB,QAAQ,CAAC,QAAQ,EAAE,UAAU,CAAC;IAE9B,mCAAmC;IACnC,QAAQ,CAAC,SAAS,EAAE,oBAAoB,CAAC;IAEzC,8IAA8I;IAC9I,QAAQ,CAAC,cAAc,CAAC,EAAE,OAAO,CAAC;IAElC,qHAAqH;IACrH,QAAQ,CAAC,qBAAqB,CAAC,EAAE,MAAM,CAAC;CACzC;AAED;;GAEG;AACH,oBAAY,cAAc;IACxB,yBAAyB;IACzB,QAAQ,IAAI;IACZ,sBAAsB;IACtB,KAAK,IAAI;CACV;AAED;;GAEG;AACH,oBAAY,gBAAgB,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,cAAc,CAAC;AAEjF;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,sDAAsD;IACtD,SAAS,EAAE,aAAa,CAAC;IAEzB;;;OAGG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IAE5C,oDAAoD;IACpD,QAAQ,CAAC,UAAU,EAAE,eAAe,CAAC;IAErC;;OAEG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,gBAAgB,CAAC;CACxC;AAED,gBAAgB;AAChB,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,eAAe,CAAC;IACzB,OAAO,CAAC,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC;CACxB;AAED,gBAAgB;AAChB,qBAAa,SAAS;IACpB,OAAO,CAAC,MAAM,CAAC,OAAO,CAAkC;mBAEnC,OAAO;WAUd,YAAY,CAAC,QAAQ,EAAE,aAAa,GAAG,WAAW,GAAG,SAAS;WAIxD,QAAQ,CAAC,CAAC,EAAE,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,CAAC,GAAG,EAAE,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC;CAUvG;AAED;;;EAGE;AACF,qBAAa,mBAAmB;IAC9B,gBAAuB,cAAc,mBAAmB;IACxD,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,CAAyB;IACpD,OAAO,CAAC,MAAM,CAAC,UAAU,CAAiD;WAE5D,SAAS,IAAI,YAAY;WASzB,OAAO,IAAI,IAAI;WAUf,WAAW,CAAC,UAAU,EAAE,eAAe,GAAG,aAAa;IAKrE,OAAO,CAAC,MAAM,KAAK,UAAU,GAqB5B;IAED,qKAAqK;IACrK,OAAO,CAAC,MAAM,CAAC,qBAAqB;IAIpC,OAAO,CAAC,MAAM,CAAC,YAAY;WASP,MAAM,CAAC,UAAU,EAAE,eAAe,GAAG,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,WAAW,CAAC,cAAc,CAAA;KAAE,CAAC;mBAoCtG,eAAe;IAYpC;;;OAGG;WACiB,kBAAkB,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,WAAW,CAAC;CAGvF;AAED;;GAEG;AACH,qBAAa,mBAAmB;WAChB,SAAS,CAAC,QAAQ,EAAE,UAAU,GAAG,YAAY;WAI7C,WAAW,CAAC,UAAU,EAAE,eAAe,GAAG,aAAa;WAKjD,eAAe,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,UAAU,CAAC;IAKlF,+BAA+B;WACX,kBAAkB,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,WAAW,CAAC;mBAIjE,eAAe;mBASf,eAAe;CAKrC;AAED,iBAAiB;AACjB,qBAAa,iBAAiB;IAC5B,gBAAuB,YAAY,gBAAqB,WAAW,KAAK,IAAI,EAAI;IAChF,gBAAuB,YAAY,gBAAqB,WAAW,KAAK,IAAI,EAAI;WAClE,MAAM,CAAC,UAAU,EAAE,eAAe;mBAE3B,UAAU;WAmBX,wBAAwB,CAAC,OAAO,EAAE,eAAe;IAkDrE,uGAAuG;WACnF,kBAAkB,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAiB/E,6FAA6F;WAC/E,uBAAuB,CAAC,UAAU,EAAE,eAAe,EAAE,UAAU,EAAE,UAAU;IAyBzF,4DAA4D;WAC9C,gBAAgB,CAAC,UAAU,EAAE,eAAe,EAAE,QAAQ,EAAE,aAAa,GAAG,OAAO;IAmB7F,uEAAuE;WACzD,gBAAgB,CAAC,OAAO,EAAE,eAAe,GAAG,UAAU,GAAG,SAAS;CAgBjF"}
|
|
@@ -18,6 +18,7 @@ const CloudSqlite_1 = require("./CloudSqlite");
|
|
|
18
18
|
const IModelDb_1 = require("./IModelDb");
|
|
19
19
|
const IModelHost_1 = require("./IModelHost");
|
|
20
20
|
const IModelJsFs_1 = require("./IModelJsFs");
|
|
21
|
+
const imodeljs_native_1 = require("@bentley/imodeljs-native");
|
|
21
22
|
const loggerCategory = BackendLoggerCategory_1.BackendLoggerCategory.IModelDb;
|
|
22
23
|
/** Return value from [[ProgressFunction]].
|
|
23
24
|
* @public
|
|
@@ -233,6 +234,7 @@ class CheckpointManager {
|
|
|
233
234
|
const traceInfo = { iTwinId: checkpoint.iTwinId, iModelId: checkpoint.iModelId, changeset: checkpoint.changeset };
|
|
234
235
|
try {
|
|
235
236
|
// Open checkpoint for write
|
|
237
|
+
core_bentley_1.Logger.setLevel(imodeljs_native_1.NativeLoggerCategory.SQLite, core_bentley_1.LogLevel.None); // Ignores noisy error messages when applying changesets.
|
|
236
238
|
const db = IModelDb_1.SnapshotDb.openForApplyChangesets(targetFile);
|
|
237
239
|
const nativeDb = db.nativeDb;
|
|
238
240
|
try {
|
|
@@ -258,6 +260,7 @@ class CheckpointManager {
|
|
|
258
260
|
}
|
|
259
261
|
}
|
|
260
262
|
finally {
|
|
263
|
+
core_bentley_1.Logger.setLevel(imodeljs_native_1.NativeLoggerCategory.SQLite, core_bentley_1.LogLevel.Error); // Turn logging back on after applying changesets.
|
|
261
264
|
db.saveChanges();
|
|
262
265
|
db.close();
|
|
263
266
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CheckpointManager.js","sourceRoot":"","sources":["../../src/CheckpointManager.ts"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\r\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\r\n* See LICENSE.md in the project root for license terms and full copyright notice.\r\n*--------------------------------------------------------------------------------------------*/\r\n/** @packageDocumentation\r\n * @module iModels\r\n */\r\n\r\n// cspell:ignore BLOCKCACHE\r\n\r\nimport * as path from \"path\";\r\nimport { BeEvent, ChangeSetStatus, Guid, GuidString, IModelStatus, Logger, Mutable, OpenMode, StopWatch } from \"@itwin/core-bentley\";\r\nimport {\r\n BriefcaseIdValue, ChangesetId, ChangesetIdWithIndex, ChangesetIndexAndId, IModelError, IModelVersion, LocalDirName, LocalFileName,\r\n} from \"@itwin/core-common\";\r\nimport { V2CheckpointAccessProps } from \"./BackendHubAccess\";\r\nimport { BackendLoggerCategory } from \"./BackendLoggerCategory\";\r\nimport { BriefcaseManager } from \"./BriefcaseManager\";\r\nimport { CloudSqlite } from \"./CloudSqlite\";\r\nimport { SnapshotDb, TokenArg } from \"./IModelDb\";\r\nimport { IModelHost } from \"./IModelHost\";\r\nimport { IModelJsFs } from \"./IModelJsFs\";\r\n\r\nconst loggerCategory = BackendLoggerCategory.IModelDb;\r\n\r\n/**\r\n * Properties of a checkpoint\r\n * @public\r\n */\r\nexport interface CheckpointProps extends TokenArg {\r\n readonly expectV2?: boolean;\r\n\r\n /** iTwin that the iModel belongs to */\r\n readonly iTwinId: GuidString;\r\n\r\n /** Id of the iModel */\r\n readonly iModelId: GuidString;\r\n\r\n /** changeset for the checkpoint */\r\n readonly changeset: ChangesetIdWithIndex;\r\n\r\n /** If true, then the latest successful v2 checkpoint at or before the provided changeset will be returned when calling queryV2Checkpoint. */\r\n readonly allowPreceding?: boolean;\r\n\r\n /** The number of seconds before the current token expires to attempt to reacquire a new token. Default is 1 hour. */\r\n readonly reattachSafetySeconds?: number;\r\n}\r\n\r\n/** Return value from [[ProgressFunction]].\r\n * @public\r\n */\r\nexport enum ProgressStatus {\r\n /** Continue download. */\r\n Continue = 0,\r\n /** Abort download. */\r\n Abort = 1,\r\n}\r\n\r\n/** Called to show progress during a download. If this function returns non-zero, the download is aborted.\r\n * @public\r\n */\r\nexport type ProgressFunction = (loaded: number, total: number) => ProgressStatus;\r\n\r\n/** The parameters that specify a request to download a checkpoint file from iModelHub.\r\n * @internal\r\n */\r\nexport interface DownloadRequest {\r\n /** name of local file to hold the downloaded data. */\r\n localFile: LocalFileName;\r\n\r\n /** A list of full fileName paths to test before downloading. If a valid file exists by one of these names,\r\n * no download is performed and `localFile` is updated to reflect the fact that the file exists with that name.\r\n * This can be used, for example, to look for checkpoints from previous versions if the naming strategy changes.\r\n */\r\n readonly aliasFiles?: ReadonlyArray<string>;\r\n\r\n /** Properties of the checkpoint to be downloaded */\r\n readonly checkpoint: CheckpointProps;\r\n\r\n /** If present, this function will be called to indicate progress as the briefcase is downloaded. If this\r\n * function returns a non-zero value, the download is aborted.\r\n */\r\n readonly onProgress?: ProgressFunction;\r\n}\r\n\r\n/** @internal */\r\nexport interface DownloadJob {\r\n request: DownloadRequest;\r\n promise?: Promise<any>;\r\n}\r\n\r\n/** @internal */\r\nexport class Downloads {\r\n private static _active = new Map<string, DownloadJob>();\r\n\r\n private static async process<T>(job: DownloadJob, fn: (job: DownloadJob) => Promise<T>) {\r\n const jobName = job.request.localFile; // save this, it can change inside call to `fn`!\r\n this._active.set(jobName, job);\r\n try {\r\n return await fn(job);\r\n } finally {\r\n this._active.delete(jobName);\r\n }\r\n }\r\n\r\n public static isInProgress(pathName: LocalFileName): DownloadJob | undefined {\r\n return this._active.get(pathName);\r\n }\r\n\r\n public static async download<T>(request: DownloadRequest, downloadFn: (job: DownloadJob) => Promise<T>) {\r\n const pathName = request.localFile;\r\n let job = this.isInProgress(pathName);\r\n if (undefined !== job)\r\n return job.promise;\r\n\r\n IModelJsFs.recursiveMkDirSync(path.dirname(pathName));\r\n job = { request };\r\n return job.promise = this.process(job, downloadFn);\r\n }\r\n}\r\n\r\n/**\r\n * Utility class for opening V2 checkpoints from cloud containers, and also for downloading them.\r\n * @internal\r\n*/\r\nexport class V2CheckpointManager {\r\n public static readonly cloudCacheName = \"v2Checkpoints\";\r\n private static _cloudCache?: CloudSqlite.CloudCache;\r\n private static containers = new Map<string, CloudSqlite.CloudContainer>();\r\n\r\n public static getFolder(): LocalDirName {\r\n const cloudCachePath = path.join(BriefcaseManager.cacheDir, V2CheckpointManager.cloudCacheName);\r\n if (!(IModelJsFs.existsSync(cloudCachePath))) {\r\n IModelJsFs.recursiveMkDirSync(cloudCachePath);\r\n }\r\n return cloudCachePath;\r\n }\r\n\r\n /* only used by tests that reset the state of the v2checkpointmanager. all dbs should be closed before calling this function. */\r\n public static cleanup(): void {\r\n for (const [_, value] of this.containers.entries()) {\r\n if (value.isConnected)\r\n value.detach();\r\n }\r\n this._cloudCache?.destroy();\r\n this._cloudCache = undefined;\r\n this.containers.clear();\r\n }\r\n\r\n public static getFileName(checkpoint: CheckpointProps): LocalFileName {\r\n const changesetId = checkpoint.changeset.id || \"first\";\r\n return path.join(this.getFolder(), `${changesetId}.bim`);\r\n }\r\n\r\n private static get cloudCache(): CloudSqlite.CloudCache {\r\n if (!this._cloudCache) {\r\n let rootDir = process.env.CHECKPOINT_CACHE_DIR;\r\n if (!rootDir) {\r\n rootDir = this.getFolder();\r\n Logger.logWarning(loggerCategory, `No CHECKPOINT_CACHE_DIR found in process.env, using ${rootDir} instead.`);\r\n } else {\r\n // Make sure the checkpoint_cache_dir has an iTwinDaemon specific file in it, otherwise fall back to other directory.\r\n if (!(IModelJsFs.existsSync(path.join(rootDir, \"portnumber.bcv\")))) {\r\n rootDir = this.getFolder();\r\n Logger.logWarning(loggerCategory, `No evidence of the iTwinDaemon in provided CHECKPOINT_CACHE_DIR: ${process.env.CHECKPOINT_CACHE_DIR}, using ${rootDir} instead.`);\r\n }\r\n }\r\n\r\n this._cloudCache = CloudSqlite.createCloudCache({ name: this.cloudCacheName, rootDir });\r\n\r\n // Its fine if its not a daemon, but lets log an info message\r\n if (!this._cloudCache.isDaemon)\r\n Logger.logInfo(loggerCategory, \"V2Checkpoint manager running with no iTwinDaemon.\");\r\n }\r\n return this._cloudCache;\r\n }\r\n\r\n /** Member names differ slightly between the V2Checkpoint api and the CloudSqlite api. Add aliases `accessName` for `accountName` and `accessToken` for `sasToken` */\r\n private static toCloudContainerProps(from: V2CheckpointAccessProps): CloudSqlite.ContainerAccessProps {\r\n return { ...from, accessName: from.accountName, accessToken: from.sasToken };\r\n }\r\n\r\n private static getContainer(v2Props: V2CheckpointAccessProps) {\r\n let container = this.containers.get(v2Props.containerId);\r\n if (!container) {\r\n container = CloudSqlite.createCloudContainer(this.toCloudContainerProps(v2Props));\r\n this.containers.set(v2Props.containerId, container);\r\n }\r\n return container;\r\n }\r\n\r\n public static async attach(checkpoint: CheckpointProps): Promise<{ dbName: string, container: CloudSqlite.CloudContainer }> {\r\n let v2props: V2CheckpointAccessProps | undefined;\r\n try {\r\n v2props = await IModelHost.hubAccess.queryV2Checkpoint(checkpoint);\r\n if (!v2props)\r\n throw new Error(\"no checkpoint\");\r\n } catch (err: any) {\r\n throw new IModelError(IModelStatus.NotFound, `V2 checkpoint not found: err: ${err.message}`);\r\n }\r\n\r\n try {\r\n const container = this.getContainer(v2props);\r\n const dbName = v2props.dbName;\r\n if (!container.isConnected)\r\n container.connect(this.cloudCache);\r\n container.checkForChanges();\r\n if (IModelHost.appWorkspace.settings.getBoolean(\"Checkpoints/prefetch\", false)) {\r\n const logPrefetch = async (prefetch: CloudSqlite.CloudPrefetch) => {\r\n const stopwatch = new StopWatch(`[${container.containerId}/${dbName}]`, true);\r\n Logger.logInfo(loggerCategory, `Starting prefetch of ${stopwatch.description}`);\r\n const done = await prefetch.promise;\r\n Logger.logInfo(loggerCategory, `Prefetch of ${stopwatch.description} complete=${done} (${stopwatch.elapsedSeconds} seconds)`);\r\n };\r\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\r\n logPrefetch(CloudSqlite.startCloudPrefetch(container, dbName));\r\n }\r\n return { dbName, container };\r\n } catch (e: any) {\r\n const error = `Cloud cache connect failed: ${e.message}`;\r\n if (checkpoint.expectV2)\r\n Logger.logError(loggerCategory, error);\r\n\r\n throw new IModelError(e.errorNumber, error);\r\n }\r\n }\r\n\r\n private static async performDownload(job: DownloadJob): Promise<ChangesetId> {\r\n const request = job.request;\r\n const v2props: V2CheckpointAccessProps | undefined = await IModelHost.hubAccess.queryV2Checkpoint({...request.checkpoint, allowPreceding: true});\r\n if (!v2props)\r\n throw new IModelError(IModelStatus.NotFound, \"V2 checkpoint not found\");\r\n\r\n CheckpointManager.onDownloadV2.raiseEvent(job);\r\n const container = CloudSqlite.createCloudContainer(this.toCloudContainerProps(v2props));\r\n await CloudSqlite.transferDb(\"download\", container, { dbName: v2props.dbName, localFileName: request.localFile, onProgress: request.onProgress });\r\n return request.checkpoint.changeset.id;\r\n }\r\n\r\n /** Fully download a V2 checkpoint to a local file that can be used to create a briefcase or to work offline.\r\n * @returns a Promise that is resolved when the download completes with the changesetId of the downloaded checkpoint (which will\r\n * be the same as the requested changesetId or the most recent checkpoint before it.)\r\n */\r\n public static async downloadCheckpoint(request: DownloadRequest): Promise<ChangesetId> {\r\n return Downloads.download(request, async (job: DownloadJob) => this.performDownload(job));\r\n }\r\n}\r\n\r\n/** Utility class to deal with downloading V1 checkpoints from iModelHub.\r\n * @internal\r\n */\r\nexport class V1CheckpointManager {\r\n public static getFolder(iModelId: GuidString): LocalDirName {\r\n return path.join(BriefcaseManager.getIModelPath(iModelId), \"checkpoints\");\r\n }\r\n\r\n public static getFileName(checkpoint: CheckpointProps): LocalFileName {\r\n const changesetId = checkpoint.changeset.id || \"first\";\r\n return path.join(this.getFolder(checkpoint.iModelId), `${changesetId}.bim`);\r\n }\r\n\r\n public static async getCheckpointDb(request: DownloadRequest): Promise<SnapshotDb> {\r\n const db = SnapshotDb.tryFindByKey(CheckpointManager.getKey(request.checkpoint));\r\n return (undefined !== db) ? db : Downloads.download(request, async (job: DownloadJob) => this.downloadAndOpen(job));\r\n }\r\n\r\n /** Download a V1 checkpoint */\r\n public static async downloadCheckpoint(request: DownloadRequest): Promise<ChangesetId> {\r\n return Downloads.download(request, async (job: DownloadJob) => this.performDownload(job));\r\n }\r\n\r\n private static async downloadAndOpen(job: DownloadJob) {\r\n const db = CheckpointManager.tryOpenLocalFile(job.request);\r\n if (db)\r\n return db;\r\n await this.performDownload(job);\r\n await CheckpointManager.updateToRequestedVersion(job.request);\r\n return SnapshotDb.openCheckpointV1(job.request.localFile, job.request.checkpoint);\r\n }\r\n\r\n private static async performDownload(job: DownloadJob): Promise<ChangesetId> {\r\n CheckpointManager.onDownloadV1.raiseEvent(job);\r\n // eslint-disable-next-line deprecation/deprecation\r\n return (await IModelHost.hubAccess.downloadV1Checkpoint(job.request)).id;\r\n }\r\n}\r\n\r\n/** @internal */\r\nexport class CheckpointManager {\r\n public static readonly onDownloadV1 = new BeEvent<(job: DownloadJob) => void>();\r\n public static readonly onDownloadV2 = new BeEvent<(job: DownloadJob) => void>();\r\n public static getKey(checkpoint: CheckpointProps) { return `${checkpoint.iModelId}:${checkpoint.changeset.id}`; }\r\n\r\n private static async doDownload(request: DownloadRequest): Promise<ChangesetId> {\r\n try {\r\n // first see if there's a V2 checkpoint available.\r\n const changesetId = await V2CheckpointManager.downloadCheckpoint(request);\r\n if (changesetId !== request.checkpoint.changeset.id)\r\n Logger.logInfo(loggerCategory, `Downloaded previous v2 checkpoint because requested checkpoint not found.`, {requestedChangesetId: request.checkpoint.changeset.id, iModelId: request.checkpoint.iModelId, changesetId, iTwinId: request.checkpoint.iTwinId });\r\n else\r\n Logger.logInfo(loggerCategory, `Downloaded v2 checkpoint.`, { iModelId: request.checkpoint.iModelId, changesetId: request.checkpoint.changeset.id, iTwinId: request.checkpoint.iTwinId });\r\n return changesetId;\r\n } catch (error: any) {\r\n if (error.errorNumber === IModelStatus.NotFound) { // No V2 checkpoint available, try a v1 checkpoint\r\n const changeset = await V1CheckpointManager.downloadCheckpoint(request);\r\n Logger.logWarning(loggerCategory, `Got an error downloading v2 checkpoint, but downloaded v1 checkpoint successfully!`, { error, iModelId: request.checkpoint.iModelId, iTwinId: request.checkpoint.iTwinId, requestedChangesetId: request.checkpoint.changeset.id, changesetId: changeset });\r\n return changeset;\r\n }\r\n throw error; // most likely, was aborted\r\n }\r\n }\r\n\r\n public static async updateToRequestedVersion(request: DownloadRequest) {\r\n const checkpoint = request.checkpoint;\r\n const targetFile = request.localFile;\r\n const traceInfo = { iTwinId: checkpoint.iTwinId, iModelId: checkpoint.iModelId, changeset: checkpoint.changeset };\r\n try {\r\n // Open checkpoint for write\r\n const db = SnapshotDb.openForApplyChangesets(targetFile);\r\n const nativeDb = db.nativeDb;\r\n try {\r\n\r\n if (nativeDb.hasPendingTxns()) {\r\n Logger.logWarning(loggerCategory, \"Checkpoint with Txns found - deleting them\", () => traceInfo);\r\n nativeDb.deleteAllTxns();\r\n }\r\n\r\n if (nativeDb.getBriefcaseId() !== BriefcaseIdValue.Unassigned)\r\n nativeDb.resetBriefcaseId(BriefcaseIdValue.Unassigned);\r\n\r\n CheckpointManager.validateCheckpointGuids(checkpoint, db);\r\n // Apply change sets if necessary\r\n const currentChangeset: Mutable<ChangesetIndexAndId> = nativeDb.getCurrentChangeset();\r\n if (currentChangeset.id !== checkpoint.changeset.id) {\r\n const accessToken = checkpoint.accessToken;\r\n const toIndex = checkpoint.changeset.index ??\r\n (await IModelHost.hubAccess.getChangesetFromVersion({ accessToken, iModelId: checkpoint.iModelId, version: IModelVersion.asOfChangeSet(checkpoint.changeset.id) })).index;\r\n await BriefcaseManager.pullAndApplyChangesets(db, { accessToken, toIndex });\r\n } else {\r\n // make sure the parent changeset index is saved in the file - old versions didn't have it.\r\n currentChangeset.index = checkpoint.changeset.index!; // eslint-disable-line @typescript-eslint/no-non-null-assertion\r\n nativeDb.saveLocalValue(\"parentChangeSet\", JSON.stringify(currentChangeset));\r\n }\r\n } finally {\r\n db.saveChanges();\r\n db.close();\r\n }\r\n } catch (error: any) {\r\n\r\n Logger.logError(loggerCategory, \"Error downloading checkpoint - deleting it\", () => traceInfo);\r\n IModelJsFs.removeSync(targetFile);\r\n\r\n if (error.errorNumber === ChangeSetStatus.CorruptedChangeStream || error.errorNumber === ChangeSetStatus.InvalidId || error.errorNumber === ChangeSetStatus.InvalidVersion) {\r\n Logger.logError(loggerCategory, \"Detected potential corruption of change sets. Deleting them to enable retries\", () => traceInfo);\r\n BriefcaseManager.deleteChangeSetsFromLocalDisk(checkpoint.iModelId);\r\n }\r\n throw error;\r\n }\r\n }\r\n\r\n /** Download a checkpoint file from iModelHub into a local file specified in the request parameters. */\r\n public static async downloadCheckpoint(request: DownloadRequest): Promise<void> {\r\n if (this.verifyCheckpoint(request.checkpoint, request.localFile))\r\n return;\r\n\r\n if (request.aliasFiles) {\r\n for (const alias of request.aliasFiles) {\r\n if (this.verifyCheckpoint(request.checkpoint, alias)) {\r\n request.localFile = alias;\r\n return;\r\n }\r\n }\r\n }\r\n\r\n await this.doDownload(request);\r\n return this.updateToRequestedVersion(request);\r\n }\r\n\r\n /** checks a file's dbGuid & iTwinId for consistency, and updates the dbGuid when possible */\r\n public static validateCheckpointGuids(checkpoint: CheckpointProps, snapshotDb: SnapshotDb) {\r\n const traceInfo = { iTwinId: checkpoint.iTwinId, iModelId: checkpoint.iModelId };\r\n\r\n const nativeDb = snapshotDb.nativeDb;\r\n const dbChangeset = nativeDb.getCurrentChangeset();\r\n const iModelId = Guid.normalize(nativeDb.getIModelId());\r\n if (iModelId !== Guid.normalize(checkpoint.iModelId)) {\r\n if (nativeDb.isReadonly())\r\n throw new IModelError(IModelStatus.ValidationFailed, \"iModelId is not properly set up in the checkpoint\");\r\n\r\n Logger.logWarning(loggerCategory, \"iModelId is not properly set up in the checkpoint. Updated checkpoint to the correct iModelId.\", () => ({ ...traceInfo, dbGuid: iModelId }));\r\n const iModelIdNormalized = Guid.normalize(checkpoint.iModelId);\r\n nativeDb.setIModelId(iModelIdNormalized);\r\n (snapshotDb as any)._iModelId = iModelIdNormalized;\r\n // Required to reset the ChangeSetId because setDbGuid clears the value.\r\n nativeDb.saveLocalValue(\"ParentChangeSetId\", dbChangeset.id);\r\n if (undefined !== dbChangeset.index)\r\n nativeDb.saveLocalValue(\"parentChangeSet\", JSON.stringify(dbChangeset));\r\n }\r\n\r\n const iTwinId = Guid.normalize(nativeDb.getITwinId());\r\n if (iTwinId !== Guid.normalize(checkpoint.iTwinId))\r\n throw new IModelError(IModelStatus.ValidationFailed, \"iTwinId was not properly set up in the checkpoint\");\r\n }\r\n\r\n /** @returns true if the file is the checkpoint requested */\r\n public static verifyCheckpoint(checkpoint: CheckpointProps, fileName: LocalFileName): boolean {\r\n if (!IModelJsFs.existsSync(fileName))\r\n return false;\r\n\r\n const nativeDb = new IModelHost.platform.DgnDb();\r\n try {\r\n nativeDb.openIModel(fileName, OpenMode.Readonly);\r\n } catch (error) {\r\n return false;\r\n }\r\n\r\n const isValid = checkpoint.iModelId === nativeDb.getIModelId() && checkpoint.changeset.id === nativeDb.getCurrentChangeset().id;\r\n nativeDb.closeIModel();\r\n if (!isValid)\r\n IModelJsFs.removeSync(fileName);\r\n\r\n return isValid;\r\n }\r\n\r\n /** try to open an existing local file to satisfy a download request */\r\n public static tryOpenLocalFile(request: DownloadRequest): SnapshotDb | undefined {\r\n const checkpoint = request.checkpoint;\r\n if (this.verifyCheckpoint(checkpoint, request.localFile))\r\n return SnapshotDb.openCheckpointV1(request.localFile, checkpoint);\r\n\r\n // check a list of aliases for finding checkpoints downloaded to non-default locations (e.g. from older versions)\r\n if (request.aliasFiles) {\r\n for (const alias of request.aliasFiles) {\r\n if (this.verifyCheckpoint(checkpoint, alias)) {\r\n request.localFile = alias;\r\n return SnapshotDb.openCheckpointV1(alias, checkpoint);\r\n }\r\n }\r\n }\r\n return undefined;\r\n }\r\n}\r\n"]}
|
|
1
|
+
{"version":3,"file":"CheckpointManager.js","sourceRoot":"","sources":["../../src/CheckpointManager.ts"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\r\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\r\n* See LICENSE.md in the project root for license terms and full copyright notice.\r\n*--------------------------------------------------------------------------------------------*/\r\n/** @packageDocumentation\r\n * @module iModels\r\n */\r\n\r\n// cspell:ignore BLOCKCACHE\r\n\r\nimport * as path from \"path\";\r\nimport { BeEvent, ChangeSetStatus, Guid, GuidString, IModelStatus, Logger, LogLevel, Mutable, OpenMode, StopWatch } from \"@itwin/core-bentley\";\r\nimport {\r\n BriefcaseIdValue, ChangesetId, ChangesetIdWithIndex, ChangesetIndexAndId, IModelError, IModelVersion, LocalDirName, LocalFileName,\r\n} from \"@itwin/core-common\";\r\nimport { V2CheckpointAccessProps } from \"./BackendHubAccess\";\r\nimport { BackendLoggerCategory } from \"./BackendLoggerCategory\";\r\nimport { BriefcaseManager } from \"./BriefcaseManager\";\r\nimport { CloudSqlite } from \"./CloudSqlite\";\r\nimport { SnapshotDb, TokenArg } from \"./IModelDb\";\r\nimport { IModelHost } from \"./IModelHost\";\r\nimport { IModelJsFs } from \"./IModelJsFs\";\r\nimport { NativeLoggerCategory } from \"@bentley/imodeljs-native\";\r\n\r\nconst loggerCategory = BackendLoggerCategory.IModelDb;\r\n\r\n/**\r\n * Properties of a checkpoint\r\n * @public\r\n */\r\nexport interface CheckpointProps extends TokenArg {\r\n readonly expectV2?: boolean;\r\n\r\n /** iTwin that the iModel belongs to */\r\n readonly iTwinId: GuidString;\r\n\r\n /** Id of the iModel */\r\n readonly iModelId: GuidString;\r\n\r\n /** changeset for the checkpoint */\r\n readonly changeset: ChangesetIdWithIndex;\r\n\r\n /** If true, then the latest successful v2 checkpoint at or before the provided changeset will be returned when calling queryV2Checkpoint. */\r\n readonly allowPreceding?: boolean;\r\n\r\n /** The number of seconds before the current token expires to attempt to reacquire a new token. Default is 1 hour. */\r\n readonly reattachSafetySeconds?: number;\r\n}\r\n\r\n/** Return value from [[ProgressFunction]].\r\n * @public\r\n */\r\nexport enum ProgressStatus {\r\n /** Continue download. */\r\n Continue = 0,\r\n /** Abort download. */\r\n Abort = 1,\r\n}\r\n\r\n/** Called to show progress during a download. If this function returns non-zero, the download is aborted.\r\n * @public\r\n */\r\nexport type ProgressFunction = (loaded: number, total: number) => ProgressStatus;\r\n\r\n/** The parameters that specify a request to download a checkpoint file from iModelHub.\r\n * @internal\r\n */\r\nexport interface DownloadRequest {\r\n /** name of local file to hold the downloaded data. */\r\n localFile: LocalFileName;\r\n\r\n /** A list of full fileName paths to test before downloading. If a valid file exists by one of these names,\r\n * no download is performed and `localFile` is updated to reflect the fact that the file exists with that name.\r\n * This can be used, for example, to look for checkpoints from previous versions if the naming strategy changes.\r\n */\r\n readonly aliasFiles?: ReadonlyArray<string>;\r\n\r\n /** Properties of the checkpoint to be downloaded */\r\n readonly checkpoint: CheckpointProps;\r\n\r\n /** If present, this function will be called to indicate progress as the briefcase is downloaded. If this\r\n * function returns a non-zero value, the download is aborted.\r\n */\r\n readonly onProgress?: ProgressFunction;\r\n}\r\n\r\n/** @internal */\r\nexport interface DownloadJob {\r\n request: DownloadRequest;\r\n promise?: Promise<any>;\r\n}\r\n\r\n/** @internal */\r\nexport class Downloads {\r\n private static _active = new Map<string, DownloadJob>();\r\n\r\n private static async process<T>(job: DownloadJob, fn: (job: DownloadJob) => Promise<T>) {\r\n const jobName = job.request.localFile; // save this, it can change inside call to `fn`!\r\n this._active.set(jobName, job);\r\n try {\r\n return await fn(job);\r\n } finally {\r\n this._active.delete(jobName);\r\n }\r\n }\r\n\r\n public static isInProgress(pathName: LocalFileName): DownloadJob | undefined {\r\n return this._active.get(pathName);\r\n }\r\n\r\n public static async download<T>(request: DownloadRequest, downloadFn: (job: DownloadJob) => Promise<T>) {\r\n const pathName = request.localFile;\r\n let job = this.isInProgress(pathName);\r\n if (undefined !== job)\r\n return job.promise;\r\n\r\n IModelJsFs.recursiveMkDirSync(path.dirname(pathName));\r\n job = { request };\r\n return job.promise = this.process(job, downloadFn);\r\n }\r\n}\r\n\r\n/**\r\n * Utility class for opening V2 checkpoints from cloud containers, and also for downloading them.\r\n * @internal\r\n*/\r\nexport class V2CheckpointManager {\r\n public static readonly cloudCacheName = \"v2Checkpoints\";\r\n private static _cloudCache?: CloudSqlite.CloudCache;\r\n private static containers = new Map<string, CloudSqlite.CloudContainer>();\r\n\r\n public static getFolder(): LocalDirName {\r\n const cloudCachePath = path.join(BriefcaseManager.cacheDir, V2CheckpointManager.cloudCacheName);\r\n if (!(IModelJsFs.existsSync(cloudCachePath))) {\r\n IModelJsFs.recursiveMkDirSync(cloudCachePath);\r\n }\r\n return cloudCachePath;\r\n }\r\n\r\n /* only used by tests that reset the state of the v2checkpointmanager. all dbs should be closed before calling this function. */\r\n public static cleanup(): void {\r\n for (const [_, value] of this.containers.entries()) {\r\n if (value.isConnected)\r\n value.detach();\r\n }\r\n this._cloudCache?.destroy();\r\n this._cloudCache = undefined;\r\n this.containers.clear();\r\n }\r\n\r\n public static getFileName(checkpoint: CheckpointProps): LocalFileName {\r\n const changesetId = checkpoint.changeset.id || \"first\";\r\n return path.join(this.getFolder(), `${changesetId}.bim`);\r\n }\r\n\r\n private static get cloudCache(): CloudSqlite.CloudCache {\r\n if (!this._cloudCache) {\r\n let rootDir = process.env.CHECKPOINT_CACHE_DIR;\r\n if (!rootDir) {\r\n rootDir = this.getFolder();\r\n Logger.logWarning(loggerCategory, `No CHECKPOINT_CACHE_DIR found in process.env, using ${rootDir} instead.`);\r\n } else {\r\n // Make sure the checkpoint_cache_dir has an iTwinDaemon specific file in it, otherwise fall back to other directory.\r\n if (!(IModelJsFs.existsSync(path.join(rootDir, \"portnumber.bcv\")))) {\r\n rootDir = this.getFolder();\r\n Logger.logWarning(loggerCategory, `No evidence of the iTwinDaemon in provided CHECKPOINT_CACHE_DIR: ${process.env.CHECKPOINT_CACHE_DIR}, using ${rootDir} instead.`);\r\n }\r\n }\r\n\r\n this._cloudCache = CloudSqlite.createCloudCache({ name: this.cloudCacheName, rootDir });\r\n\r\n // Its fine if its not a daemon, but lets log an info message\r\n if (!this._cloudCache.isDaemon)\r\n Logger.logInfo(loggerCategory, \"V2Checkpoint manager running with no iTwinDaemon.\");\r\n }\r\n return this._cloudCache;\r\n }\r\n\r\n /** Member names differ slightly between the V2Checkpoint api and the CloudSqlite api. Add aliases `accessName` for `accountName` and `accessToken` for `sasToken` */\r\n private static toCloudContainerProps(from: V2CheckpointAccessProps): CloudSqlite.ContainerAccessProps {\r\n return { ...from, accessName: from.accountName, accessToken: from.sasToken };\r\n }\r\n\r\n private static getContainer(v2Props: V2CheckpointAccessProps) {\r\n let container = this.containers.get(v2Props.containerId);\r\n if (!container) {\r\n container = CloudSqlite.createCloudContainer(this.toCloudContainerProps(v2Props));\r\n this.containers.set(v2Props.containerId, container);\r\n }\r\n return container;\r\n }\r\n\r\n public static async attach(checkpoint: CheckpointProps): Promise<{ dbName: string, container: CloudSqlite.CloudContainer }> {\r\n let v2props: V2CheckpointAccessProps | undefined;\r\n try {\r\n v2props = await IModelHost.hubAccess.queryV2Checkpoint(checkpoint);\r\n if (!v2props)\r\n throw new Error(\"no checkpoint\");\r\n } catch (err: any) {\r\n throw new IModelError(IModelStatus.NotFound, `V2 checkpoint not found: err: ${err.message}`);\r\n }\r\n\r\n try {\r\n const container = this.getContainer(v2props);\r\n const dbName = v2props.dbName;\r\n if (!container.isConnected)\r\n container.connect(this.cloudCache);\r\n container.checkForChanges();\r\n if (IModelHost.appWorkspace.settings.getBoolean(\"Checkpoints/prefetch\", false)) {\r\n const logPrefetch = async (prefetch: CloudSqlite.CloudPrefetch) => {\r\n const stopwatch = new StopWatch(`[${container.containerId}/${dbName}]`, true);\r\n Logger.logInfo(loggerCategory, `Starting prefetch of ${stopwatch.description}`);\r\n const done = await prefetch.promise;\r\n Logger.logInfo(loggerCategory, `Prefetch of ${stopwatch.description} complete=${done} (${stopwatch.elapsedSeconds} seconds)`);\r\n };\r\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\r\n logPrefetch(CloudSqlite.startCloudPrefetch(container, dbName));\r\n }\r\n return { dbName, container };\r\n } catch (e: any) {\r\n const error = `Cloud cache connect failed: ${e.message}`;\r\n if (checkpoint.expectV2)\r\n Logger.logError(loggerCategory, error);\r\n\r\n throw new IModelError(e.errorNumber, error);\r\n }\r\n }\r\n\r\n private static async performDownload(job: DownloadJob): Promise<ChangesetId> {\r\n const request = job.request;\r\n const v2props: V2CheckpointAccessProps | undefined = await IModelHost.hubAccess.queryV2Checkpoint({...request.checkpoint, allowPreceding: true});\r\n if (!v2props)\r\n throw new IModelError(IModelStatus.NotFound, \"V2 checkpoint not found\");\r\n\r\n CheckpointManager.onDownloadV2.raiseEvent(job);\r\n const container = CloudSqlite.createCloudContainer(this.toCloudContainerProps(v2props));\r\n await CloudSqlite.transferDb(\"download\", container, { dbName: v2props.dbName, localFileName: request.localFile, onProgress: request.onProgress });\r\n return request.checkpoint.changeset.id;\r\n }\r\n\r\n /** Fully download a V2 checkpoint to a local file that can be used to create a briefcase or to work offline.\r\n * @returns a Promise that is resolved when the download completes with the changesetId of the downloaded checkpoint (which will\r\n * be the same as the requested changesetId or the most recent checkpoint before it.)\r\n */\r\n public static async downloadCheckpoint(request: DownloadRequest): Promise<ChangesetId> {\r\n return Downloads.download(request, async (job: DownloadJob) => this.performDownload(job));\r\n }\r\n}\r\n\r\n/** Utility class to deal with downloading V1 checkpoints from iModelHub.\r\n * @internal\r\n */\r\nexport class V1CheckpointManager {\r\n public static getFolder(iModelId: GuidString): LocalDirName {\r\n return path.join(BriefcaseManager.getIModelPath(iModelId), \"checkpoints\");\r\n }\r\n\r\n public static getFileName(checkpoint: CheckpointProps): LocalFileName {\r\n const changesetId = checkpoint.changeset.id || \"first\";\r\n return path.join(this.getFolder(checkpoint.iModelId), `${changesetId}.bim`);\r\n }\r\n\r\n public static async getCheckpointDb(request: DownloadRequest): Promise<SnapshotDb> {\r\n const db = SnapshotDb.tryFindByKey(CheckpointManager.getKey(request.checkpoint));\r\n return (undefined !== db) ? db : Downloads.download(request, async (job: DownloadJob) => this.downloadAndOpen(job));\r\n }\r\n\r\n /** Download a V1 checkpoint */\r\n public static async downloadCheckpoint(request: DownloadRequest): Promise<ChangesetId> {\r\n return Downloads.download(request, async (job: DownloadJob) => this.performDownload(job));\r\n }\r\n\r\n private static async downloadAndOpen(job: DownloadJob) {\r\n const db = CheckpointManager.tryOpenLocalFile(job.request);\r\n if (db)\r\n return db;\r\n await this.performDownload(job);\r\n await CheckpointManager.updateToRequestedVersion(job.request);\r\n return SnapshotDb.openCheckpointV1(job.request.localFile, job.request.checkpoint);\r\n }\r\n\r\n private static async performDownload(job: DownloadJob): Promise<ChangesetId> {\r\n CheckpointManager.onDownloadV1.raiseEvent(job);\r\n // eslint-disable-next-line deprecation/deprecation\r\n return (await IModelHost.hubAccess.downloadV1Checkpoint(job.request)).id;\r\n }\r\n}\r\n\r\n/** @internal */\r\nexport class CheckpointManager {\r\n public static readonly onDownloadV1 = new BeEvent<(job: DownloadJob) => void>();\r\n public static readonly onDownloadV2 = new BeEvent<(job: DownloadJob) => void>();\r\n public static getKey(checkpoint: CheckpointProps) { return `${checkpoint.iModelId}:${checkpoint.changeset.id}`; }\r\n\r\n private static async doDownload(request: DownloadRequest): Promise<ChangesetId> {\r\n try {\r\n // first see if there's a V2 checkpoint available.\r\n const changesetId = await V2CheckpointManager.downloadCheckpoint(request);\r\n if (changesetId !== request.checkpoint.changeset.id)\r\n Logger.logInfo(loggerCategory, `Downloaded previous v2 checkpoint because requested checkpoint not found.`, {requestedChangesetId: request.checkpoint.changeset.id, iModelId: request.checkpoint.iModelId, changesetId, iTwinId: request.checkpoint.iTwinId });\r\n else\r\n Logger.logInfo(loggerCategory, `Downloaded v2 checkpoint.`, { iModelId: request.checkpoint.iModelId, changesetId: request.checkpoint.changeset.id, iTwinId: request.checkpoint.iTwinId });\r\n return changesetId;\r\n } catch (error: any) {\r\n if (error.errorNumber === IModelStatus.NotFound) { // No V2 checkpoint available, try a v1 checkpoint\r\n const changeset = await V1CheckpointManager.downloadCheckpoint(request);\r\n Logger.logWarning(loggerCategory, `Got an error downloading v2 checkpoint, but downloaded v1 checkpoint successfully!`, { error, iModelId: request.checkpoint.iModelId, iTwinId: request.checkpoint.iTwinId, requestedChangesetId: request.checkpoint.changeset.id, changesetId: changeset });\r\n return changeset;\r\n }\r\n throw error; // most likely, was aborted\r\n }\r\n }\r\n\r\n public static async updateToRequestedVersion(request: DownloadRequest) {\r\n const checkpoint = request.checkpoint;\r\n const targetFile = request.localFile;\r\n const traceInfo = { iTwinId: checkpoint.iTwinId, iModelId: checkpoint.iModelId, changeset: checkpoint.changeset };\r\n try {\r\n // Open checkpoint for write\r\n Logger.setLevel(NativeLoggerCategory.SQLite, LogLevel.None); // Ignores noisy error messages when applying changesets.\r\n const db = SnapshotDb.openForApplyChangesets(targetFile);\r\n const nativeDb = db.nativeDb;\r\n try {\r\n\r\n if (nativeDb.hasPendingTxns()) {\r\n Logger.logWarning(loggerCategory, \"Checkpoint with Txns found - deleting them\", () => traceInfo);\r\n nativeDb.deleteAllTxns();\r\n }\r\n\r\n if (nativeDb.getBriefcaseId() !== BriefcaseIdValue.Unassigned)\r\n nativeDb.resetBriefcaseId(BriefcaseIdValue.Unassigned);\r\n\r\n CheckpointManager.validateCheckpointGuids(checkpoint, db);\r\n // Apply change sets if necessary\r\n const currentChangeset: Mutable<ChangesetIndexAndId> = nativeDb.getCurrentChangeset();\r\n if (currentChangeset.id !== checkpoint.changeset.id) {\r\n const accessToken = checkpoint.accessToken;\r\n const toIndex = checkpoint.changeset.index ??\r\n (await IModelHost.hubAccess.getChangesetFromVersion({ accessToken, iModelId: checkpoint.iModelId, version: IModelVersion.asOfChangeSet(checkpoint.changeset.id) })).index;\r\n await BriefcaseManager.pullAndApplyChangesets(db, { accessToken, toIndex });\r\n } else {\r\n // make sure the parent changeset index is saved in the file - old versions didn't have it.\r\n currentChangeset.index = checkpoint.changeset.index!; // eslint-disable-line @typescript-eslint/no-non-null-assertion\r\n nativeDb.saveLocalValue(\"parentChangeSet\", JSON.stringify(currentChangeset));\r\n }\r\n } finally {\r\n Logger.setLevel(NativeLoggerCategory.SQLite, LogLevel.Error); // Turn logging back on after applying changesets.\r\n db.saveChanges();\r\n db.close();\r\n }\r\n } catch (error: any) {\r\n\r\n Logger.logError(loggerCategory, \"Error downloading checkpoint - deleting it\", () => traceInfo);\r\n IModelJsFs.removeSync(targetFile);\r\n\r\n if (error.errorNumber === ChangeSetStatus.CorruptedChangeStream || error.errorNumber === ChangeSetStatus.InvalidId || error.errorNumber === ChangeSetStatus.InvalidVersion) {\r\n Logger.logError(loggerCategory, \"Detected potential corruption of change sets. Deleting them to enable retries\", () => traceInfo);\r\n BriefcaseManager.deleteChangeSetsFromLocalDisk(checkpoint.iModelId);\r\n }\r\n throw error;\r\n }\r\n }\r\n\r\n /** Download a checkpoint file from iModelHub into a local file specified in the request parameters. */\r\n public static async downloadCheckpoint(request: DownloadRequest): Promise<void> {\r\n if (this.verifyCheckpoint(request.checkpoint, request.localFile))\r\n return;\r\n\r\n if (request.aliasFiles) {\r\n for (const alias of request.aliasFiles) {\r\n if (this.verifyCheckpoint(request.checkpoint, alias)) {\r\n request.localFile = alias;\r\n return;\r\n }\r\n }\r\n }\r\n\r\n await this.doDownload(request);\r\n return this.updateToRequestedVersion(request);\r\n }\r\n\r\n /** checks a file's dbGuid & iTwinId for consistency, and updates the dbGuid when possible */\r\n public static validateCheckpointGuids(checkpoint: CheckpointProps, snapshotDb: SnapshotDb) {\r\n const traceInfo = { iTwinId: checkpoint.iTwinId, iModelId: checkpoint.iModelId };\r\n\r\n const nativeDb = snapshotDb.nativeDb;\r\n const dbChangeset = nativeDb.getCurrentChangeset();\r\n const iModelId = Guid.normalize(nativeDb.getIModelId());\r\n if (iModelId !== Guid.normalize(checkpoint.iModelId)) {\r\n if (nativeDb.isReadonly())\r\n throw new IModelError(IModelStatus.ValidationFailed, \"iModelId is not properly set up in the checkpoint\");\r\n\r\n Logger.logWarning(loggerCategory, \"iModelId is not properly set up in the checkpoint. Updated checkpoint to the correct iModelId.\", () => ({ ...traceInfo, dbGuid: iModelId }));\r\n const iModelIdNormalized = Guid.normalize(checkpoint.iModelId);\r\n nativeDb.setIModelId(iModelIdNormalized);\r\n (snapshotDb as any)._iModelId = iModelIdNormalized;\r\n // Required to reset the ChangeSetId because setDbGuid clears the value.\r\n nativeDb.saveLocalValue(\"ParentChangeSetId\", dbChangeset.id);\r\n if (undefined !== dbChangeset.index)\r\n nativeDb.saveLocalValue(\"parentChangeSet\", JSON.stringify(dbChangeset));\r\n }\r\n\r\n const iTwinId = Guid.normalize(nativeDb.getITwinId());\r\n if (iTwinId !== Guid.normalize(checkpoint.iTwinId))\r\n throw new IModelError(IModelStatus.ValidationFailed, \"iTwinId was not properly set up in the checkpoint\");\r\n }\r\n\r\n /** @returns true if the file is the checkpoint requested */\r\n public static verifyCheckpoint(checkpoint: CheckpointProps, fileName: LocalFileName): boolean {\r\n if (!IModelJsFs.existsSync(fileName))\r\n return false;\r\n\r\n const nativeDb = new IModelHost.platform.DgnDb();\r\n try {\r\n nativeDb.openIModel(fileName, OpenMode.Readonly);\r\n } catch (error) {\r\n return false;\r\n }\r\n\r\n const isValid = checkpoint.iModelId === nativeDb.getIModelId() && checkpoint.changeset.id === nativeDb.getCurrentChangeset().id;\r\n nativeDb.closeIModel();\r\n if (!isValid)\r\n IModelJsFs.removeSync(fileName);\r\n\r\n return isValid;\r\n }\r\n\r\n /** try to open an existing local file to satisfy a download request */\r\n public static tryOpenLocalFile(request: DownloadRequest): SnapshotDb | undefined {\r\n const checkpoint = request.checkpoint;\r\n if (this.verifyCheckpoint(checkpoint, request.localFile))\r\n return SnapshotDb.openCheckpointV1(request.localFile, checkpoint);\r\n\r\n // check a list of aliases for finding checkpoints downloaded to non-default locations (e.g. from older versions)\r\n if (request.aliasFiles) {\r\n for (const alias of request.aliasFiles) {\r\n if (this.verifyCheckpoint(checkpoint, alias)) {\r\n request.localFile = alias;\r\n return SnapshotDb.openCheckpointV1(alias, checkpoint);\r\n }\r\n }\r\n }\r\n return undefined;\r\n }\r\n}\r\n"]}
|
package/lib/cjs/CloudSqlite.d.ts
CHANGED
|
@@ -155,7 +155,10 @@ export declare namespace CloudSqlite {
|
|
|
155
155
|
/** destroy this CloudCache. All CloudContainers should be detached before calling this. */
|
|
156
156
|
destroy(): void;
|
|
157
157
|
}
|
|
158
|
-
/** A CloudSqlite container that may be connected to a CloudCache.
|
|
158
|
+
/** A CloudSqlite container that may be connected to a CloudCache.
|
|
159
|
+
* @note All methods and accessors of this interface (other than `initializeContainer`) require that the `connect` method be successfully called first.
|
|
160
|
+
* Otherwise they will throw an exception or return meaningless values.
|
|
161
|
+
*/
|
|
159
162
|
interface CloudContainer {
|
|
160
163
|
readonly cache?: CloudCache;
|
|
161
164
|
/** The ContainerId. */
|
|
@@ -185,13 +188,21 @@ export declare namespace CloudSqlite {
|
|
|
185
188
|
checksumBlockNames?: boolean;
|
|
186
189
|
blockSize?: number;
|
|
187
190
|
}): void;
|
|
191
|
+
/**
|
|
192
|
+
* Connect this CloudContainer to a CloudCache for reading or writing its manifest, write lock, and databases.
|
|
193
|
+
* @note A CloudCache is a local directory holding copies of information from the cloud. Its content is persistent across sessions,
|
|
194
|
+
* but this method must be called each session to (re)establish the connection to the cache. If the CloudCache was previously populated,
|
|
195
|
+
* this method may be called and will succeed *even when offline* or without a valid `accessToken`.
|
|
196
|
+
* @note all operations that access the contents of databases or the manifest require this method be successfully called (i.e. `isConnected === true`).
|
|
197
|
+
*/
|
|
198
|
+
connect(cache: CloudCache): void;
|
|
188
199
|
/**
|
|
189
200
|
* Attempt to acquire the write lock for this CloudContainer. For this to succeed:
|
|
190
201
|
* 1. it must be connected to a `CloudCache`
|
|
191
202
|
* 2. this CloudContainer must have been constructed with `writeable: true`
|
|
192
203
|
* 3. the `accessToken` must authorize write access
|
|
193
204
|
* 4. no other process may be holding an unexpired write lock
|
|
194
|
-
* @throws
|
|
205
|
+
* @throws if any of the above conditions fail
|
|
195
206
|
* @note Write locks *expire* after the duration specified in the `durationSeconds` property of the constructor argument, in case a process
|
|
196
207
|
* crashes or otherwise fails to release the lock. Calling `acquireWriteLock` with the lock already held resets the lock duration from the current time,
|
|
197
208
|
* so long running processes should call this method periodically to ensure their lock doesn't expire (they should also make sure their accessToken is refreshed
|
|
@@ -219,17 +230,10 @@ export declare namespace CloudSqlite {
|
|
|
219
230
|
* on any database in the container.
|
|
220
231
|
*/
|
|
221
232
|
abandonChanges(): void;
|
|
222
|
-
/**
|
|
223
|
-
* Connect this CloudContainer to a CloudCache for reading or writing its manifest, write lock, and databases.
|
|
224
|
-
* @note A CloudCache is a local directory holding copies of information from the cloud. Its content is persistent across sessions,
|
|
225
|
-
* but this method must be called each session to (re)establish the connection to the cache. If the CloudCache was previously populated,
|
|
226
|
-
* this method may be called and will succeed *even when offline* or without a valid `accessToken`.
|
|
227
|
-
* @note all operations that access the contents of databases or the manifest require this method be called (`isConnected === true`).
|
|
228
|
-
*/
|
|
229
|
-
connect(cache: CloudCache): void;
|
|
230
233
|
/**
|
|
231
234
|
* Disconnect this CloudContainer from its CloudCache. There must be no open databases from this container. Leaves the container attached to the
|
|
232
235
|
* CloudCache so it is available for future sessions.
|
|
236
|
+
* @note This function does nothing (and does not throw) if the CloudContainer is not connected to a CloudCache.
|
|
233
237
|
*/
|
|
234
238
|
disconnect(): void;
|
|
235
239
|
/**
|
|
@@ -330,6 +334,7 @@ export declare namespace CloudSqlite {
|
|
|
330
334
|
* @param user the name to be displayed to other users in the event they attempt to obtain the lock while it is held by us
|
|
331
335
|
* @param container the CloudContainer for which the lock is to be acquired
|
|
332
336
|
* @param busyHandler if present, function called when the write lock is currently held by another user.
|
|
337
|
+
* @throws if [[container]] is not connected to a CloudCache.
|
|
333
338
|
*/
|
|
334
339
|
function acquireWriteLock(user: string, container: CloudContainer, busyHandler?: WriteLockBusyHandler): Promise<void>;
|
|
335
340
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CloudSqlite.d.ts","sourceRoot":"","sources":["../../src/CloudSqlite.ts"],"names":[],"mappings":"AAIA;;GAEG;AAKH,OAAO,EAAmB,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEjE;;GAEG;AACH,yBAAiB,WAAW,CAAC;IAC3B,SAAgB,oBAAoB,CAAC,IAAI,EAAE,oBAAoB,GAAG,cAAc,CAE/E;IACD,SAAgB,gBAAgB,CAAC,IAAI,EAAE,WAAW,CAAC,UAAU,GAAG,WAAW,CAAC,UAAU,CAErF;IACD,SAAgB,kBAAkB,CAAC,SAAS,EAAE,WAAW,CAAC,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,CAAC,aAAa,GAAG,WAAW,CAAC,aAAa,CAErJ;IAED,0FAA0F;IAC1F,UAAiB,kBAAkB;QACjC,iGAAiG;QACjG,WAAW,EAAE,MAAM,CAAC;QACpB,4DAA4D;QAC5D,UAAU,EAAE,MAAM,CAAC;KACpB;IAED,sCAAsC;IACtC,UAAiB,cAAc;QAC7B,iCAAiC;QACjC,WAAW,EAAE,MAAM,CAAC;QACpB,4DAA4D;QAC5D,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,oIAAoI;QACpI,WAAW,EAAE,MAAM,CAAC;QACpB,+HAA+H;QAC/H,SAAS,CAAC,EAAE,OAAO,CAAC;QACpB,6GAA6G;QAC7G,MAAM,CAAC,EAAE,OAAO,CAAC;KAClB;IAED,4FAA4F;IAC5F,UAAiB,aAAa;QAC5B,iDAAiD;QACjD,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;QAC7B,yFAAyF;QACzF,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;QAC7B,iHAAiH;QACjH,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;QAC7B,kIAAkI;QAClI,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;QAC/B,qGAAqG;QACrG,QAAQ,CAAC,KAAK,EAAE,EAAE,GAAG,QAAQ,GAAG,SAAS,CAAC;KAC3C;IAED,gDAAgD;IAChD,KAAY,oBAAoB,GAAG,kBAAkB,GAAG,cAAc,GAAG;QACvE,iIAAiI;QACjI,eAAe,CAAC,EAAE,MAAM,CAAC;KAC1B,CAAC;IAEF,kEAAkE;IAClE,UAAiB,UAAU;QACzB;6GACqG;QACrG,MAAM,EAAE,MAAM,CAAC;KAChB;IAED,kEAAkE;IAClE,UAAiB,OAAQ,SAAQ,UAAU;QACzC,yDAAyD;QACzD,aAAa,EAAE,aAAa,CAAC;KAC9B;IAED,KAAY,iBAAiB,GAAG,QAAQ,GAAG,UAAU,CAAC;IACtD,UAAiB,gBAAgB;QAC/B,0HAA0H;QAC1H,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;KACxD;IAED,UAAiB,cAAc;QAC7B,+DAA+D;QAC/D,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB;IAED,UAAiB,aAAc,SAAQ,cAAc;QACnD,iEAAiE;QACjE,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,iGAAiG;QACjG,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB;IAED,KAAY,eAAe,GAAG,OAAO,GAAG,gBAAgB,GAAG,cAAc,CAAC;IAE1E,4CAA4C;IAC5C,UAAiB,UAAW,SAAQ,cAAc;QAChD,0JAA0J;QAC1J,OAAO,EAAE,MAAM,CAAC;QAChB,+FAA+F;QAC/F,IAAI,EAAE,MAAM,CAAC;QACb,oHAAoH;QACpH,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,yDAAyD;QACzD,eAAe,CAAC,EAAE,OAAO,CAAC;KAC3B;IAED;;OAEG;IACH,UAAiB,gBAAgB;QAC/B,gIAAgI;QAChI,IAAI,CAAC,EAAE,MAAM,CAAC;QACd;;WAEG;QACH,QAAQ,EAAE,MAAM,CAAC;QACjB,8DAA8D;QAC9D,YAAY,EAAE,MAAM,CAAC;QACrB;;;WAGG;QACH,SAAS,CAAC,EAAE,oBAAoB,CAAC;KAClC;IAED,gBAAgB;IAChB,UAAiB,eAAe;QAC9B,+DAA+D;QAC/D,IAAI,EAAE,MAAM,CAAC;QACb,oDAAoD;QACpD,MAAM,EAAE,MAAM,CAAC;QACf,kEAAkE;QAClE,SAAS,EAAE,cAAc,CAAC;QAC1B,yFAAyF;QACzF,WAAW,CAAC,EAAE,oBAAoB,CAAC;KACpC;IAED,qDAAqD;IACrD,KAAY,WAAW;QACrB,0CAA0C;QAC1C,IAAI,IAAO;QACX,sDAAsD;QACtD,WAAW,IAAO;QAClB,iDAAiD;QACjD,WAAW,IAAO;QAClB,uGAAuG;QACvG,eAAe,IAAO;QACtB,qCAAqC;QACrC,GAAG,MAAO;QACV,sBAAsB;QACtB,IAAI,IAAI;KACT;IAED;;;;;OAKG;IACH,UAAiB,UAAU;QACzB,iEAAiE;QACjE,IAAI,QAAQ,IAAI,OAAO,CAAC;QACxB,oCAAoC;QACpC,IAAI,IAAI,IAAI,MAAM,CAAC;QACnB,8DAA8D;QAC9D,IAAI,OAAO,IAAI,YAAY,CAAC;QAC5B,mEAAmE;QACnE,IAAI,IAAI,IAAI,UAAU,CAAC;QACvB;;;;;WAKG;QACH,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;QAC/B,2FAA2F;QAC3F,OAAO,IAAI,IAAI,CAAC;KACjB;IAED
|
|
1
|
+
{"version":3,"file":"CloudSqlite.d.ts","sourceRoot":"","sources":["../../src/CloudSqlite.ts"],"names":[],"mappings":"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"}
|
package/lib/cjs/CloudSqlite.js
CHANGED
|
@@ -104,6 +104,7 @@ var CloudSqlite;
|
|
|
104
104
|
* @param user the name to be displayed to other users in the event they attempt to obtain the lock while it is held by us
|
|
105
105
|
* @param container the CloudContainer for which the lock is to be acquired
|
|
106
106
|
* @param busyHandler if present, function called when the write lock is currently held by another user.
|
|
107
|
+
* @throws if [[container]] is not connected to a CloudCache.
|
|
107
108
|
*/
|
|
108
109
|
async function acquireWriteLock(user, container, busyHandler) {
|
|
109
110
|
if (container.hasWriteLock)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CloudSqlite.js","sourceRoot":"","sources":["../../src/CloudSqlite.ts"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\r\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\r\n* See LICENSE.md in the project root for license terms and full copyright notice.\r\n*--------------------------------------------------------------------------------------------*/\r\n/** @packageDocumentation\r\n * @module SQLiteDb\r\n */\r\n\r\nimport { mkdirSync } from \"fs\";\r\nimport { dirname } from \"path\";\r\nimport { NativeLibrary } from \"@bentley/imodeljs-native\";\r\nimport { BriefcaseStatus, GuidString } from \"@itwin/core-bentley\";\r\nimport { LocalDirName, LocalFileName } from \"@itwin/core-common\";\r\n\r\n/** Types for using SQLite files stored in cloud containers.\r\n * @beta\r\n */\r\nexport namespace CloudSqlite {\r\n export function createCloudContainer(args: ContainerAccessProps): CloudContainer {\r\n return new NativeLibrary.nativeLib.CloudContainer(args);\r\n }\r\n export function createCloudCache(args: CloudSqlite.CacheProps): CloudSqlite.CloudCache {\r\n return new NativeLibrary.nativeLib.CloudCache(args);\r\n }\r\n export function startCloudPrefetch(container: CloudSqlite.CloudContainer, dbName: string, args?: CloudSqlite.PrefetchProps): CloudSqlite.CloudPrefetch {\r\n return new NativeLibrary.nativeLib.CloudPrefetch(container, dbName, args);\r\n }\r\n\r\n /** Properties that specify how to access the account for a cloud blob-store container. */\r\n export interface AccountAccessProps {\r\n /** blob storage module: e.g. \"azure\", \"google\", \"aws\". May also include URI style parameters. */\r\n storageType: string;\r\n /** blob store account name, or a URI for custom domains. */\r\n accessName: string;\r\n }\r\n\r\n /** Properties of a CloudContainer. */\r\n export interface ContainerProps {\r\n /** the name of the container. */\r\n containerId: string;\r\n /** an alias for the container. Defaults to `containerId` */\r\n alias?: string;\r\n /** token that grants access to the container. For sas=1 `storageType`s, this is the sasToken. For sas=0, this is the account key */\r\n accessToken: string;\r\n /** if true, container is attached with write permissions, and accessToken must provide write access to the cloud container. */\r\n writeable?: boolean;\r\n /** if true, container is attached in \"secure\" mode (blocks are encrypted). Only supported in daemon mode. */\r\n secure?: boolean;\r\n }\r\n\r\n /** Returned from `CloudContainer.queryDatabase` describing one database in the container */\r\n export interface CachedDbProps {\r\n /** The total of (4Mb) blocks in the database. */\r\n readonly totalBlocks: number;\r\n /** the number of blocks of the database that have been downloaded into the CloudCache */\r\n readonly localBlocks: number;\r\n /** the number of blocks from this database that have been modified in the CloudCache and need to be uploaded. */\r\n readonly dirtyBlocks: number;\r\n /** If true, the database currently has transactions in the WAL file and may not be uploaded until they have been checkPointed. */\r\n readonly transactions: boolean;\r\n /** the state of this database. Indicates whether the database is new or deleted since last upload */\r\n readonly state: \"\" | \"copied\" | \"deleted\";\r\n }\r\n\r\n /** Properties for accessing a CloudContainer */\r\n export type ContainerAccessProps = AccountAccessProps & ContainerProps & {\r\n /** Duration for holding write lock, in seconds. After this time the write lock expires if not refreshed. Default is one hour. */\r\n durationSeconds?: number;\r\n };\r\n\r\n /** The name of a CloudSqlite database within a CloudContainer. */\r\n export interface DbNameProp {\r\n /** the name of the database within the CloudContainer.\r\n * @note names of databases within a CloudContainer are always **case sensitive** on all platforms.*/\r\n dbName: string;\r\n }\r\n\r\n /** Properties for accessing a database within a CloudContainer */\r\n export interface DbProps extends DbNameProp {\r\n /** the name of the local file to access the database. */\r\n localFileName: LocalFileName;\r\n }\r\n\r\n export type TransferDirection = \"upload\" | \"download\";\r\n export interface TransferProgress {\r\n /** a user-supplied progress function called during the transfer operation. Return a non-0 value to abort the transfer. */\r\n onProgress?: (loaded: number, total: number) => number;\r\n }\r\n\r\n export interface CloudHttpProps {\r\n /** The number of simultaneous HTTP requests. Default is 6. */\r\n nRequests?: number;\r\n }\r\n\r\n export interface PrefetchProps extends CloudHttpProps {\r\n /** timeout between requests, in milliseconds. Default is 100. */\r\n timeout?: number;\r\n /** The number of prefetch requests to issue while there is foreground activity. Default is 3. */\r\n minRequests?: number;\r\n }\r\n\r\n export type TransferDbProps = DbProps & TransferProgress & CloudHttpProps;\r\n\r\n /** Properties for creating a CloudCache. */\r\n export interface CacheProps extends CloudHttpProps {\r\n /** full path of directory for cache to store its files. Must be on a (preferably fast) local drive, and must be empty when the cache is first created. */\r\n rootDir: string;\r\n /** name of this cache. It is possible to have more than one CloudCache in the same session. */\r\n name: string;\r\n /** maximum cache Size. Must be a number followed by either M (for megabytes) or G (for gigabytes.) Default is 1G */\r\n cacheSize?: string;\r\n /** turn on diagnostics for `curl` (outputs to stderr) */\r\n curlDiagnostics?: boolean;\r\n }\r\n\r\n /** Parameters used to obtain the write lock on a cloud container\r\n * @internal\r\n */\r\n export interface ObtainLockParams {\r\n /** The name of the user attempting to acquire the write lock. This name will be shown to other users while the lock is held. */\r\n user?: string;\r\n /** number of times to retry in the event the lock currently held by someone else.\r\n * After this number of attempts, `onFailure` is called. Default is 20.\r\n */\r\n nRetries: number;\r\n /** Delay between retries, in milliseconds. Default is 100. */\r\n retryDelayMs: number;\r\n /** function called if lock cannot be obtained after all retries. It is called with the name of the user currently holding the lock and\r\n * generally is expected that the user will be consulted whether to wait further.\r\n * If this function returns \"stop\", an exception will be thrown. Otherwise the retry cycle is restarted.\r\n */\r\n onFailure?: WriteLockBusyHandler;\r\n }\r\n\r\n /** @internal */\r\n export interface LockAndOpenArgs {\r\n /** the name to be displayed in the event of lock collisions */\r\n user: string;\r\n /** the name of the database within the container */\r\n dbName: string;\r\n /** the CloudContainer on which the operation will be performed */\r\n container: CloudContainer;\r\n /** if present, function called when the write lock is currently held by another user. */\r\n busyHandler?: WriteLockBusyHandler;\r\n }\r\n\r\n /** Logging categories for `CloudCache.setLogMask` */\r\n export enum LoggingMask {\r\n /** log all HTTP requests and responses */\r\n HTTP = 0x01,\r\n /** log as blocks become dirty and must be uploaded */\r\n DirtyBlocks = 0x02,\r\n /** log as blocks are added to the delete list */\r\n AddToDelete = 0x04,\r\n /** log container lifecycle events (e.g. authorization requests, disconnects, and state transitions) */\r\n LifecycleEvents = 0x08,\r\n /** Turn on all logging categories */\r\n All = 0xff,\r\n /** Disable logging */\r\n None = 0,\r\n }\r\n\r\n /**\r\n * A cache for storing data from CloudSqlite databases. This object refers to a directory on a local filesystem\r\n * and is used to **connect** CloudContainers so they may be accessed. The contents of the cache directory are entirely\r\n * controlled by CloudSqlite and should be empty when the cache is first created and never modified directly. It maintains\r\n * the state of the local data across sessions.\r\n */\r\n export interface CloudCache {\r\n /** `true` if this CloudCache is connected to a daemon process */\r\n get isDaemon(): boolean;\r\n /** The name for this CloudCache. */\r\n get name(): string;\r\n /** The root directory of this CloudCache on a local drive. */\r\n get rootDir(): LocalDirName;\r\n /** The guid for this CloudCache. Used for acquiring write lock. */\r\n get guid(): GuidString;\r\n /** Configure logging for this CloudCache.\r\n * @param mask A bitmask of `LoggingMask` values\r\n * @note this method does nothing if [[isDaemon]] is true. Daemon logging is configured when the daemon is started.\r\n * @note HTTP logging can be happen on multiple threads and may be buffered. To see buffered log messages, periodically call\r\n * `IModelHost.flushLog`\r\n */\r\n setLogMask(mask: number): void;\r\n /** destroy this CloudCache. All CloudContainers should be detached before calling this. */\r\n destroy(): void;\r\n }\r\n\r\n /** A CloudSqlite container that may be connected to a CloudCache. */\r\n export interface CloudContainer {\r\n readonly cache?: CloudCache;\r\n /** The ContainerId. */\r\n get containerId(): string;\r\n /** The *alias* to identify this CloudContainer in a CloudCache. Usually just the ContainerId. */\r\n get alias(): string;\r\n /** true if this CloudContainer is currently connected to a CloudCache via the `connect` method. */\r\n get isConnected(): boolean;\r\n /** true if this CloudContainer was created with the `writeable` flag (and its `accessToken` supplies write access). */\r\n get isWriteable(): boolean;\r\n /** true if this CloudContainer currently holds the write lock for its container in the cloud. */\r\n get hasWriteLock(): boolean;\r\n /** true if this CloudContainer has local changes that have not be uploaded to its container in the cloud. */\r\n get hasLocalChanges(): boolean;\r\n /** The current accessToken providing access to the cloud container */\r\n get accessToken(): string;\r\n set accessToken(val: string);\r\n /** Get the number of garbage blocks in this container that can be purged. */\r\n get garbageBlocks(): number;\r\n /** The block size for this CloudContainer. */\r\n get blockSize(): number;\r\n\r\n /**\r\n * initialize a cloud blob-store container to be used as a new Sqlite CloudContainer. This creates the manifest, and should be\r\n * performed on an empty container. If an existing manifest is present, it is destroyed and a new one is created (essentially emptying the container.)\r\n */\r\n initializeContainer(opts?: { checksumBlockNames?: boolean, blockSize?: number }): void;\r\n\r\n /**\r\n * Attempt to acquire the write lock for this CloudContainer. For this to succeed:\r\n * 1. it must be connected to a `CloudCache`\r\n * 2. this CloudContainer must have been constructed with `writeable: true`\r\n * 3. the `accessToken` must authorize write access\r\n * 4. no other process may be holding an unexpired write lock\r\n * @throws exception if any of the above conditions fail\r\n * @note Write locks *expire* after the duration specified in the `durationSeconds` property of the constructor argument, in case a process\r\n * crashes or otherwise fails to release the lock. Calling `acquireWriteLock` with the lock already held resets the lock duration from the current time,\r\n * so long running processes should call this method periodically to ensure their lock doesn't expire (they should also make sure their accessToken is refreshed\r\n * before it expires.)\r\n * @note on success, the manifest is polled before the promise resolves.\r\n * @param user An identifier of the process/user locking the CloudContainer. In the event of a write lock\r\n * collision, this string will be included in the exception string of the *other* process attempting to obtain a write lock.\r\n */\r\n acquireWriteLock(user: string): void;\r\n\r\n /**\r\n * Release the write lock if it is currently held.\r\n * @note if there are local changes that have not been uploaded, they are automatically uploaded before the write lock is released.\r\n * @note if the write lock is not held, this method does nothing.\r\n */\r\n releaseWriteLock(): void;\r\n\r\n /**\r\n * Destroy any currently valid write lock from this or any other process. This is obviously very dangerous and defeats the purpose of write locking.\r\n * This method exists only for administrator tools to clear a failed process without waiting for the expiration period. It can also be useful for tests.\r\n * For this to succeed, all of the conditions of `acquireWriteLock` must be true other than #4.\r\n */\r\n clearWriteLock(): void;\r\n\r\n /**\r\n * Abandon any local changes in this container. If the write lock is currently held, it is released.\r\n * This function fails with BE_SQLITE_BUSY if one or more clients have open read or write transactions\r\n * on any database in the container.\r\n */\r\n abandonChanges(): void;\r\n\r\n /**\r\n * Connect this CloudContainer to a CloudCache for reading or writing its manifest, write lock, and databases.\r\n * @note A CloudCache is a local directory holding copies of information from the cloud. Its content is persistent across sessions,\r\n * but this method must be called each session to (re)establish the connection to the cache. If the CloudCache was previously populated,\r\n * this method may be called and will succeed *even when offline* or without a valid `accessToken`.\r\n * @note all operations that access the contents of databases or the manifest require this method be called (`isConnected === true`).\r\n */\r\n connect(cache: CloudCache): void;\r\n\r\n /**\r\n * Disconnect this CloudContainer from its CloudCache. There must be no open databases from this container. Leaves the container attached to the\r\n * CloudCache so it is available for future sessions.\r\n */\r\n disconnect(): void;\r\n\r\n /**\r\n * Permanently Detach and Disconnect this CloudContainer from its CloudCache. There must be no open databases from this container.\r\n */\r\n detach(): void;\r\n\r\n /**\r\n * Poll cloud storage for changes from other processes. *No changes* made by other processes are visible to\r\n * this CloudContainer unless/until this method is called.\r\n * @note this is automatically called whenever the write lock is obtained to ensure all changes are against the latest version.\r\n */\r\n checkForChanges(): void;\r\n\r\n /**\r\n * Upload any changed blocks from all databases in this CloudContainer.\r\n * @note this is called automatically from `releaseWriteLock` before the write lock is released. It is only necessary to call this directly if you\r\n * wish to upload changes while the write lock is still held.\r\n * @see hasLocalChanges\r\n */\r\n uploadChanges(): Promise<void>;\r\n\r\n /**\r\n * Clean any unused deleted blocks from cloud storage. When a database is written, a subset of its blocks are replaced\r\n * by new versions, sometimes leaving the originals unused. In this case, they are not deleted immediately.\r\n * Instead, they are scheduled for deletion at some later time. Calling this method deletes all blocks in the cloud container\r\n * for which the scheduled deletion time has passed.\r\n * @param nSeconds Any block that was marked as unused before this number of seconds ago will be deleted. Specifying a non-zero\r\n * value gives a period of time for other clients to refresh their manifests and stop using the now-garbage blocks. Otherwise they may get\r\n * a 404 error. Default is 1 hour.\r\n */\r\n cleanDeletedBlocks(nSeconds?: number): Promise<void>;\r\n\r\n /**\r\n * Create a copy of an existing database within this CloudContainer with a new name.\r\n * @note CloudSqlite uses copy-on-write semantics for this operation. That is, this method merely makes a\r\n * new entry in the manifest with the new name that *shares* all of its blocks with the original database.\r\n * If either database subsequently changes, the only modified blocks are not shared.\r\n */\r\n copyDatabase(dbName: string, toAlias: string): Promise<void>;\r\n\r\n /** Remove a database from this CloudContainer.\r\n * @see cleanDeletedBlocks\r\n */\r\n deleteDatabase(dbName: string): Promise<void>;\r\n\r\n /** Get the list of database names in this CloudContainer.\r\n * @param globArg if present, filter the results with SQLite [GLOB](https://www.sqlite.org/lang_expr.html#glob) operator.\r\n */\r\n queryDatabases(globArg?: string): string[];\r\n\r\n /**\r\n * Get the status of a specific database in this CloudContainer.\r\n * @param dbName the name of the database of interest\r\n */\r\n queryDatabase(dbName: string): CloudSqlite.CachedDbProps | undefined;\r\n\r\n /**\r\n * Get the SHA1 hash of the content of a database.\r\n * @param dbName the name of the database of interest\r\n * @note the hash will be empty if the database does not exist\r\n */\r\n queryDatabaseHash(dbName: string): string;\r\n }\r\n\r\n /** @internal */\r\n export interface CloudPrefetch {\r\n readonly cloudContainer: CloudContainer;\r\n readonly dbName: string;\r\n\r\n /** Cancel a currently pending prefetch. The promise will be resolved immediately after this call. */\r\n cancel(): void;\r\n\r\n /**\r\n * Promise that is resolved when the prefetch completes or is cancelled. Await this promise to ensure that the\r\n * database has been fully downloaded before going offline, for example.\r\n * @returns a Promise that resolves to `true` if the prefetch completed and the entire database is local, or `false` if it was aborted or failed.\r\n * @note the promise is *not* rejected on `cancel`. Some progress may (or may not) have been made by the request.\r\n * @note To monitor the progress being made during prefetch, call `CloudContainer.queryDatabase` periodically.\r\n */\r\n promise: Promise<boolean>;\r\n }\r\n\r\n /** @internal */\r\n export async function transferDb(direction: TransferDirection, container: CloudContainer, props: TransferDbProps) {\r\n if (direction === \"download\")\r\n mkdirSync(dirname(props.localFileName), { recursive: true }); // make sure the directory exists before starting download\r\n\r\n let timer: NodeJS.Timeout | undefined;\r\n try {\r\n const transfer = new NativeLibrary.nativeLib.CloudDbTransfer(direction, container, props);\r\n let total = 0;\r\n const onProgress = props.onProgress;\r\n if (onProgress) {\r\n timer = setInterval(async () => { // set an interval timer to show progress every 250ms\r\n const progress = transfer.getProgress();\r\n total = progress.total;\r\n if (onProgress(progress.loaded, progress.total))\r\n transfer.cancelTransfer();\r\n }, 250);\r\n }\r\n await transfer.promise;\r\n onProgress?.(total, total); // make sure we call progress func one last time when download completes\r\n } catch (err: any) {\r\n if (err.message === \"cancelled\")\r\n err.errorNumber = BriefcaseStatus.DownloadCancelled;\r\n\r\n throw err;\r\n } finally {\r\n if (timer)\r\n clearInterval(timer);\r\n }\r\n }\r\n\r\n /** Upload a database into a CloudContainer\r\n * @param container the CloudContainer holding the database. Must be connected.\r\n * @param props the properties that describe the database to be downloaded, plus optionally an `onProgress` function.\r\n * @note this function requires that the write lock be held on the container\r\n */\r\n export async function uploadDb(container: CloudContainer, props: TransferDbProps): Promise<void> {\r\n await transferDb(\"upload\", container, props);\r\n container.checkForChanges(); // re-read the manifest so the database is available locally.\r\n }\r\n\r\n /** Download a database from a CloudContainer\r\n * @param container the CloudContainer holding the database. Must be connected.\r\n * @param props the properties that describe the database to be downloaded, plus optionally an `onProgress` function.\r\n * @returns a Promise that is resolved when the download completes.\r\n * @note the download is \"restartable.\" If the transfer is aborted and then re-requested, it will continue from where\r\n * it left off rather than re-downloading the entire file.\r\n */\r\n export async function downloadDb(container: CloudContainer, props: TransferDbProps): Promise<void> {\r\n await transferDb(\"download\", container, props);\r\n }\r\n\r\n /** Optional method to be called when an attempt to acquire the write lock fails because another user currently holds it.\r\n * @param lockedBy The identifier supplied by the application/user that currently holds the lock.\r\n * @param expires a stringified Date (in local time) indicating when the lock will expire.\r\n * @return \"stop\" to give up and stop retrying. Generally, it's a good idea to wait for some time before returning.\r\n */\r\n export type WriteLockBusyHandler = (lockedBy: string, expires: string) => Promise<void | \"stop\">;\r\n\r\n /**\r\n * Attempt to acquire the write lock for a container, with retries.\r\n * If write lock is held by another user, call busyHandler if supplied. If no busyHandler, or handler returns \"stop\", throw. Otherwise try again.\r\n * @note if write lock is already held, this function does nothing.\r\n * @param user the name to be displayed to other users in the event they attempt to obtain the lock while it is held by us\r\n * @param container the CloudContainer for which the lock is to be acquired\r\n * @param busyHandler if present, function called when the write lock is currently held by another user.\r\n */\r\n export async function acquireWriteLock(user: string, container: CloudContainer, busyHandler?: WriteLockBusyHandler) {\r\n if (container.hasWriteLock)\r\n return;\r\n\r\n while (true) {\r\n try {\r\n return container.acquireWriteLock(user);\r\n } catch (e: any) {\r\n if (e.errorNumber === 5 && busyHandler && \"stop\" !== await busyHandler(e.lockedBy, e.expires)) // 5 === BE_SQLITE_BUSY\r\n continue; // busy handler wants to try again\r\n throw e;\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Perform an asynchronous write operation on a CloudContainer with the write lock held.\r\n * 1. if write lock is already held, call operation and return.\r\n * 2. attempt to acquire the write lock, with retries. Throw if unable to obtain write lock.\r\n * 3. perform the operation\r\n * 3.a if the operation throws, abandon all changes and re-throw\r\n * 4. release the write lock.\r\n * 5. return value from operation\r\n * @param user the name to be displayed to other users in the event they attempt to obtain the lock while it is held by us\r\n * @param container the CloudContainer for which the lock is to be acquired\r\n * @param operation an asynchronous operation performed with the write lock held.\r\n * @param busyHandler if present, function called when the write lock is currently held by another user.\r\n * @returns a Promise with the result of `operation`\r\n */\r\n export async function withWriteLock<T>(user: string, container: CloudContainer, operation: () => T, busyHandler?: WriteLockBusyHandler) {\r\n if (container.hasWriteLock)\r\n return operation();\r\n\r\n await acquireWriteLock(user, container, busyHandler);\r\n try {\r\n // eslint-disable-next-line @typescript-eslint/await-thenable\r\n const val = await operation(); // wait for work to finish or fail\r\n container.releaseWriteLock();\r\n return val;\r\n } catch (e) {\r\n container.abandonChanges(); // if operation threw, abandon all changes\r\n throw e;\r\n }\r\n }\r\n}\r\n"]}
|
|
1
|
+
{"version":3,"file":"CloudSqlite.js","sourceRoot":"","sources":["../../src/CloudSqlite.ts"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\r\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\r\n* See LICENSE.md in the project root for license terms and full copyright notice.\r\n*--------------------------------------------------------------------------------------------*/\r\n/** @packageDocumentation\r\n * @module SQLiteDb\r\n */\r\n\r\nimport { mkdirSync } from \"fs\";\r\nimport { dirname } from \"path\";\r\nimport { NativeLibrary } from \"@bentley/imodeljs-native\";\r\nimport { BriefcaseStatus, GuidString } from \"@itwin/core-bentley\";\r\nimport { LocalDirName, LocalFileName } from \"@itwin/core-common\";\r\n\r\n/** Types for using SQLite files stored in cloud containers.\r\n * @beta\r\n */\r\nexport namespace CloudSqlite {\r\n export function createCloudContainer(args: ContainerAccessProps): CloudContainer {\r\n return new NativeLibrary.nativeLib.CloudContainer(args);\r\n }\r\n export function createCloudCache(args: CloudSqlite.CacheProps): CloudSqlite.CloudCache {\r\n return new NativeLibrary.nativeLib.CloudCache(args);\r\n }\r\n export function startCloudPrefetch(container: CloudSqlite.CloudContainer, dbName: string, args?: CloudSqlite.PrefetchProps): CloudSqlite.CloudPrefetch {\r\n return new NativeLibrary.nativeLib.CloudPrefetch(container, dbName, args);\r\n }\r\n\r\n /** Properties that specify how to access the account for a cloud blob-store container. */\r\n export interface AccountAccessProps {\r\n /** blob storage module: e.g. \"azure\", \"google\", \"aws\". May also include URI style parameters. */\r\n storageType: string;\r\n /** blob store account name, or a URI for custom domains. */\r\n accessName: string;\r\n }\r\n\r\n /** Properties of a CloudContainer. */\r\n export interface ContainerProps {\r\n /** the name of the container. */\r\n containerId: string;\r\n /** an alias for the container. Defaults to `containerId` */\r\n alias?: string;\r\n /** token that grants access to the container. For sas=1 `storageType`s, this is the sasToken. For sas=0, this is the account key */\r\n accessToken: string;\r\n /** if true, container is attached with write permissions, and accessToken must provide write access to the cloud container. */\r\n writeable?: boolean;\r\n /** if true, container is attached in \"secure\" mode (blocks are encrypted). Only supported in daemon mode. */\r\n secure?: boolean;\r\n }\r\n\r\n /** Returned from `CloudContainer.queryDatabase` describing one database in the container */\r\n export interface CachedDbProps {\r\n /** The total of (4Mb) blocks in the database. */\r\n readonly totalBlocks: number;\r\n /** the number of blocks of the database that have been downloaded into the CloudCache */\r\n readonly localBlocks: number;\r\n /** the number of blocks from this database that have been modified in the CloudCache and need to be uploaded. */\r\n readonly dirtyBlocks: number;\r\n /** If true, the database currently has transactions in the WAL file and may not be uploaded until they have been checkPointed. */\r\n readonly transactions: boolean;\r\n /** the state of this database. Indicates whether the database is new or deleted since last upload */\r\n readonly state: \"\" | \"copied\" | \"deleted\";\r\n }\r\n\r\n /** Properties for accessing a CloudContainer */\r\n export type ContainerAccessProps = AccountAccessProps & ContainerProps & {\r\n /** Duration for holding write lock, in seconds. After this time the write lock expires if not refreshed. Default is one hour. */\r\n durationSeconds?: number;\r\n };\r\n\r\n /** The name of a CloudSqlite database within a CloudContainer. */\r\n export interface DbNameProp {\r\n /** the name of the database within the CloudContainer.\r\n * @note names of databases within a CloudContainer are always **case sensitive** on all platforms.*/\r\n dbName: string;\r\n }\r\n\r\n /** Properties for accessing a database within a CloudContainer */\r\n export interface DbProps extends DbNameProp {\r\n /** the name of the local file to access the database. */\r\n localFileName: LocalFileName;\r\n }\r\n\r\n export type TransferDirection = \"upload\" | \"download\";\r\n export interface TransferProgress {\r\n /** a user-supplied progress function called during the transfer operation. Return a non-0 value to abort the transfer. */\r\n onProgress?: (loaded: number, total: number) => number;\r\n }\r\n\r\n export interface CloudHttpProps {\r\n /** The number of simultaneous HTTP requests. Default is 6. */\r\n nRequests?: number;\r\n }\r\n\r\n export interface PrefetchProps extends CloudHttpProps {\r\n /** timeout between requests, in milliseconds. Default is 100. */\r\n timeout?: number;\r\n /** The number of prefetch requests to issue while there is foreground activity. Default is 3. */\r\n minRequests?: number;\r\n }\r\n\r\n export type TransferDbProps = DbProps & TransferProgress & CloudHttpProps;\r\n\r\n /** Properties for creating a CloudCache. */\r\n export interface CacheProps extends CloudHttpProps {\r\n /** full path of directory for cache to store its files. Must be on a (preferably fast) local drive, and must be empty when the cache is first created. */\r\n rootDir: string;\r\n /** name of this cache. It is possible to have more than one CloudCache in the same session. */\r\n name: string;\r\n /** maximum cache Size. Must be a number followed by either M (for megabytes) or G (for gigabytes.) Default is 1G */\r\n cacheSize?: string;\r\n /** turn on diagnostics for `curl` (outputs to stderr) */\r\n curlDiagnostics?: boolean;\r\n }\r\n\r\n /** Parameters used to obtain the write lock on a cloud container\r\n * @internal\r\n */\r\n export interface ObtainLockParams {\r\n /** The name of the user attempting to acquire the write lock. This name will be shown to other users while the lock is held. */\r\n user?: string;\r\n /** number of times to retry in the event the lock currently held by someone else.\r\n * After this number of attempts, `onFailure` is called. Default is 20.\r\n */\r\n nRetries: number;\r\n /** Delay between retries, in milliseconds. Default is 100. */\r\n retryDelayMs: number;\r\n /** function called if lock cannot be obtained after all retries. It is called with the name of the user currently holding the lock and\r\n * generally is expected that the user will be consulted whether to wait further.\r\n * If this function returns \"stop\", an exception will be thrown. Otherwise the retry cycle is restarted.\r\n */\r\n onFailure?: WriteLockBusyHandler;\r\n }\r\n\r\n /** @internal */\r\n export interface LockAndOpenArgs {\r\n /** the name to be displayed in the event of lock collisions */\r\n user: string;\r\n /** the name of the database within the container */\r\n dbName: string;\r\n /** the CloudContainer on which the operation will be performed */\r\n container: CloudContainer;\r\n /** if present, function called when the write lock is currently held by another user. */\r\n busyHandler?: WriteLockBusyHandler;\r\n }\r\n\r\n /** Logging categories for `CloudCache.setLogMask` */\r\n export enum LoggingMask {\r\n /** log all HTTP requests and responses */\r\n HTTP = 0x01,\r\n /** log as blocks become dirty and must be uploaded */\r\n DirtyBlocks = 0x02,\r\n /** log as blocks are added to the delete list */\r\n AddToDelete = 0x04,\r\n /** log container lifecycle events (e.g. authorization requests, disconnects, and state transitions) */\r\n LifecycleEvents = 0x08,\r\n /** Turn on all logging categories */\r\n All = 0xff,\r\n /** Disable logging */\r\n None = 0,\r\n }\r\n\r\n /**\r\n * A cache for storing data from CloudSqlite databases. This object refers to a directory on a local filesystem\r\n * and is used to **connect** CloudContainers so they may be accessed. The contents of the cache directory are entirely\r\n * controlled by CloudSqlite and should be empty when the cache is first created and never modified directly. It maintains\r\n * the state of the local data across sessions.\r\n */\r\n export interface CloudCache {\r\n /** `true` if this CloudCache is connected to a daemon process */\r\n get isDaemon(): boolean;\r\n /** The name for this CloudCache. */\r\n get name(): string;\r\n /** The root directory of this CloudCache on a local drive. */\r\n get rootDir(): LocalDirName;\r\n /** The guid for this CloudCache. Used for acquiring write lock. */\r\n get guid(): GuidString;\r\n /** Configure logging for this CloudCache.\r\n * @param mask A bitmask of `LoggingMask` values\r\n * @note this method does nothing if [[isDaemon]] is true. Daemon logging is configured when the daemon is started.\r\n * @note HTTP logging can be happen on multiple threads and may be buffered. To see buffered log messages, periodically call\r\n * `IModelHost.flushLog`\r\n */\r\n setLogMask(mask: number): void;\r\n /** destroy this CloudCache. All CloudContainers should be detached before calling this. */\r\n destroy(): void;\r\n }\r\n\r\n /** A CloudSqlite container that may be connected to a CloudCache.\r\n * @note All methods and accessors of this interface (other than `initializeContainer`) require that the `connect` method be successfully called first.\r\n * Otherwise they will throw an exception or return meaningless values.\r\n */\r\n export interface CloudContainer {\r\n readonly cache?: CloudCache;\r\n /** The ContainerId. */\r\n get containerId(): string;\r\n /** The *alias* to identify this CloudContainer in a CloudCache. Usually just the ContainerId. */\r\n get alias(): string;\r\n /** true if this CloudContainer is currently connected to a CloudCache via the `connect` method. */\r\n get isConnected(): boolean;\r\n /** true if this CloudContainer was created with the `writeable` flag (and its `accessToken` supplies write access). */\r\n get isWriteable(): boolean;\r\n /** true if this CloudContainer currently holds the write lock for its container in the cloud. */\r\n get hasWriteLock(): boolean;\r\n /** true if this CloudContainer has local changes that have not be uploaded to its container in the cloud. */\r\n get hasLocalChanges(): boolean;\r\n /** The current accessToken providing access to the cloud container */\r\n get accessToken(): string;\r\n set accessToken(val: string);\r\n /** Get the number of garbage blocks in this container that can be purged. */\r\n get garbageBlocks(): number;\r\n /** The block size for this CloudContainer. */\r\n get blockSize(): number;\r\n\r\n /**\r\n * initialize a cloud blob-store container to be used as a new Sqlite CloudContainer. This creates the manifest, and should be\r\n * performed on an empty container. If an existing manifest is present, it is destroyed and a new one is created (essentially emptying the container.)\r\n */\r\n initializeContainer(opts?: { checksumBlockNames?: boolean, blockSize?: number }): void;\r\n\r\n /**\r\n * Connect this CloudContainer to a CloudCache for reading or writing its manifest, write lock, and databases.\r\n * @note A CloudCache is a local directory holding copies of information from the cloud. Its content is persistent across sessions,\r\n * but this method must be called each session to (re)establish the connection to the cache. If the CloudCache was previously populated,\r\n * this method may be called and will succeed *even when offline* or without a valid `accessToken`.\r\n * @note all operations that access the contents of databases or the manifest require this method be successfully called (i.e. `isConnected === true`).\r\n */\r\n connect(cache: CloudCache): void;\r\n\r\n /**\r\n * Attempt to acquire the write lock for this CloudContainer. For this to succeed:\r\n * 1. it must be connected to a `CloudCache`\r\n * 2. this CloudContainer must have been constructed with `writeable: true`\r\n * 3. the `accessToken` must authorize write access\r\n * 4. no other process may be holding an unexpired write lock\r\n * @throws if any of the above conditions fail\r\n * @note Write locks *expire* after the duration specified in the `durationSeconds` property of the constructor argument, in case a process\r\n * crashes or otherwise fails to release the lock. Calling `acquireWriteLock` with the lock already held resets the lock duration from the current time,\r\n * so long running processes should call this method periodically to ensure their lock doesn't expire (they should also make sure their accessToken is refreshed\r\n * before it expires.)\r\n * @note on success, the manifest is polled before the promise resolves.\r\n * @param user An identifier of the process/user locking the CloudContainer. In the event of a write lock\r\n * collision, this string will be included in the exception string of the *other* process attempting to obtain a write lock.\r\n */\r\n acquireWriteLock(user: string): void;\r\n\r\n /**\r\n * Release the write lock if it is currently held.\r\n * @note if there are local changes that have not been uploaded, they are automatically uploaded before the write lock is released.\r\n * @note if the write lock is not held, this method does nothing.\r\n */\r\n releaseWriteLock(): void;\r\n\r\n /**\r\n * Destroy any currently valid write lock from this or any other process. This is obviously very dangerous and defeats the purpose of write locking.\r\n * This method exists only for administrator tools to clear a failed process without waiting for the expiration period. It can also be useful for tests.\r\n * For this to succeed, all of the conditions of `acquireWriteLock` must be true other than #4.\r\n */\r\n clearWriteLock(): void;\r\n\r\n /**\r\n * Abandon any local changes in this container. If the write lock is currently held, it is released.\r\n * This function fails with BE_SQLITE_BUSY if one or more clients have open read or write transactions\r\n * on any database in the container.\r\n */\r\n abandonChanges(): void;\r\n\r\n /**\r\n * Disconnect this CloudContainer from its CloudCache. There must be no open databases from this container. Leaves the container attached to the\r\n * CloudCache so it is available for future sessions.\r\n * @note This function does nothing (and does not throw) if the CloudContainer is not connected to a CloudCache.\r\n */\r\n disconnect(): void;\r\n\r\n /**\r\n * Permanently Detach and Disconnect this CloudContainer from its CloudCache. There must be no open databases from this container.\r\n */\r\n detach(): void;\r\n\r\n /**\r\n * Poll cloud storage for changes from other processes. *No changes* made by other processes are visible to\r\n * this CloudContainer unless/until this method is called.\r\n * @note this is automatically called whenever the write lock is obtained to ensure all changes are against the latest version.\r\n */\r\n checkForChanges(): void;\r\n\r\n /**\r\n * Upload any changed blocks from all databases in this CloudContainer.\r\n * @note this is called automatically from `releaseWriteLock` before the write lock is released. It is only necessary to call this directly if you\r\n * wish to upload changes while the write lock is still held.\r\n * @see hasLocalChanges\r\n */\r\n uploadChanges(): Promise<void>;\r\n\r\n /**\r\n * Clean any unused deleted blocks from cloud storage. When a database is written, a subset of its blocks are replaced\r\n * by new versions, sometimes leaving the originals unused. In this case, they are not deleted immediately.\r\n * Instead, they are scheduled for deletion at some later time. Calling this method deletes all blocks in the cloud container\r\n * for which the scheduled deletion time has passed.\r\n * @param nSeconds Any block that was marked as unused before this number of seconds ago will be deleted. Specifying a non-zero\r\n * value gives a period of time for other clients to refresh their manifests and stop using the now-garbage blocks. Otherwise they may get\r\n * a 404 error. Default is 1 hour.\r\n */\r\n cleanDeletedBlocks(nSeconds?: number): Promise<void>;\r\n\r\n /**\r\n * Create a copy of an existing database within this CloudContainer with a new name.\r\n * @note CloudSqlite uses copy-on-write semantics for this operation. That is, this method merely makes a\r\n * new entry in the manifest with the new name that *shares* all of its blocks with the original database.\r\n * If either database subsequently changes, the only modified blocks are not shared.\r\n */\r\n copyDatabase(dbName: string, toAlias: string): Promise<void>;\r\n\r\n /** Remove a database from this CloudContainer.\r\n * @see cleanDeletedBlocks\r\n */\r\n deleteDatabase(dbName: string): Promise<void>;\r\n\r\n /** Get the list of database names in this CloudContainer.\r\n * @param globArg if present, filter the results with SQLite [GLOB](https://www.sqlite.org/lang_expr.html#glob) operator.\r\n */\r\n queryDatabases(globArg?: string): string[];\r\n\r\n /**\r\n * Get the status of a specific database in this CloudContainer.\r\n * @param dbName the name of the database of interest\r\n */\r\n queryDatabase(dbName: string): CloudSqlite.CachedDbProps | undefined;\r\n\r\n /**\r\n * Get the SHA1 hash of the content of a database.\r\n * @param dbName the name of the database of interest\r\n * @note the hash will be empty if the database does not exist\r\n */\r\n queryDatabaseHash(dbName: string): string;\r\n }\r\n\r\n /** @internal */\r\n export interface CloudPrefetch {\r\n readonly cloudContainer: CloudContainer;\r\n readonly dbName: string;\r\n\r\n /** Cancel a currently pending prefetch. The promise will be resolved immediately after this call. */\r\n cancel(): void;\r\n\r\n /**\r\n * Promise that is resolved when the prefetch completes or is cancelled. Await this promise to ensure that the\r\n * database has been fully downloaded before going offline, for example.\r\n * @returns a Promise that resolves to `true` if the prefetch completed and the entire database is local, or `false` if it was aborted or failed.\r\n * @note the promise is *not* rejected on `cancel`. Some progress may (or may not) have been made by the request.\r\n * @note To monitor the progress being made during prefetch, call `CloudContainer.queryDatabase` periodically.\r\n */\r\n promise: Promise<boolean>;\r\n }\r\n\r\n /** @internal */\r\n export async function transferDb(direction: TransferDirection, container: CloudContainer, props: TransferDbProps) {\r\n if (direction === \"download\")\r\n mkdirSync(dirname(props.localFileName), { recursive: true }); // make sure the directory exists before starting download\r\n\r\n let timer: NodeJS.Timeout | undefined;\r\n try {\r\n const transfer = new NativeLibrary.nativeLib.CloudDbTransfer(direction, container, props);\r\n let total = 0;\r\n const onProgress = props.onProgress;\r\n if (onProgress) {\r\n timer = setInterval(async () => { // set an interval timer to show progress every 250ms\r\n const progress = transfer.getProgress();\r\n total = progress.total;\r\n if (onProgress(progress.loaded, progress.total))\r\n transfer.cancelTransfer();\r\n }, 250);\r\n }\r\n await transfer.promise;\r\n onProgress?.(total, total); // make sure we call progress func one last time when download completes\r\n } catch (err: any) {\r\n if (err.message === \"cancelled\")\r\n err.errorNumber = BriefcaseStatus.DownloadCancelled;\r\n\r\n throw err;\r\n } finally {\r\n if (timer)\r\n clearInterval(timer);\r\n }\r\n }\r\n\r\n /** Upload a database into a CloudContainer\r\n * @param container the CloudContainer holding the database. Must be connected.\r\n * @param props the properties that describe the database to be downloaded, plus optionally an `onProgress` function.\r\n * @note this function requires that the write lock be held on the container\r\n */\r\n export async function uploadDb(container: CloudContainer, props: TransferDbProps): Promise<void> {\r\n await transferDb(\"upload\", container, props);\r\n container.checkForChanges(); // re-read the manifest so the database is available locally.\r\n }\r\n\r\n /** Download a database from a CloudContainer\r\n * @param container the CloudContainer holding the database. Must be connected.\r\n * @param props the properties that describe the database to be downloaded, plus optionally an `onProgress` function.\r\n * @returns a Promise that is resolved when the download completes.\r\n * @note the download is \"restartable.\" If the transfer is aborted and then re-requested, it will continue from where\r\n * it left off rather than re-downloading the entire file.\r\n */\r\n export async function downloadDb(container: CloudContainer, props: TransferDbProps): Promise<void> {\r\n await transferDb(\"download\", container, props);\r\n }\r\n\r\n /** Optional method to be called when an attempt to acquire the write lock fails because another user currently holds it.\r\n * @param lockedBy The identifier supplied by the application/user that currently holds the lock.\r\n * @param expires a stringified Date (in local time) indicating when the lock will expire.\r\n * @return \"stop\" to give up and stop retrying. Generally, it's a good idea to wait for some time before returning.\r\n */\r\n export type WriteLockBusyHandler = (lockedBy: string, expires: string) => Promise<void | \"stop\">;\r\n\r\n /**\r\n * Attempt to acquire the write lock for a container, with retries.\r\n * If write lock is held by another user, call busyHandler if supplied. If no busyHandler, or handler returns \"stop\", throw. Otherwise try again.\r\n * @note if write lock is already held, this function does nothing.\r\n * @param user the name to be displayed to other users in the event they attempt to obtain the lock while it is held by us\r\n * @param container the CloudContainer for which the lock is to be acquired\r\n * @param busyHandler if present, function called when the write lock is currently held by another user.\r\n * @throws if [[container]] is not connected to a CloudCache.\r\n */\r\n export async function acquireWriteLock(user: string, container: CloudContainer, busyHandler?: WriteLockBusyHandler) {\r\n if (container.hasWriteLock)\r\n return;\r\n\r\n while (true) {\r\n try {\r\n return container.acquireWriteLock(user);\r\n } catch (e: any) {\r\n if (e.errorNumber === 5 && busyHandler && \"stop\" !== await busyHandler(e.lockedBy, e.expires)) // 5 === BE_SQLITE_BUSY\r\n continue; // busy handler wants to try again\r\n throw e;\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Perform an asynchronous write operation on a CloudContainer with the write lock held.\r\n * 1. if write lock is already held, call operation and return.\r\n * 2. attempt to acquire the write lock, with retries. Throw if unable to obtain write lock.\r\n * 3. perform the operation\r\n * 3.a if the operation throws, abandon all changes and re-throw\r\n * 4. release the write lock.\r\n * 5. return value from operation\r\n * @param user the name to be displayed to other users in the event they attempt to obtain the lock while it is held by us\r\n * @param container the CloudContainer for which the lock is to be acquired\r\n * @param operation an asynchronous operation performed with the write lock held.\r\n * @param busyHandler if present, function called when the write lock is currently held by another user.\r\n * @returns a Promise with the result of `operation`\r\n */\r\n export async function withWriteLock<T>(user: string, container: CloudContainer, operation: () => T, busyHandler?: WriteLockBusyHandler) {\r\n if (container.hasWriteLock)\r\n return operation();\r\n\r\n await acquireWriteLock(user, container, busyHandler);\r\n try {\r\n // eslint-disable-next-line @typescript-eslint/await-thenable\r\n const val = await operation(); // wait for work to finish or fail\r\n container.releaseWriteLock();\r\n return val;\r\n } catch (e) {\r\n container.abandonChanges(); // if operation threw, abandon all changes\r\n throw e;\r\n }\r\n }\r\n}\r\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@itwin/core-backend",
|
|
3
|
-
"version": "4.0.0-dev.
|
|
3
|
+
"version": "4.0.0-dev.46",
|
|
4
4
|
"description": "iTwin.js backend components",
|
|
5
5
|
"main": "lib/cjs/core-backend.js",
|
|
6
6
|
"typings": "lib/cjs/core-backend",
|
|
@@ -24,9 +24,9 @@
|
|
|
24
24
|
"url": "http://www.bentley.com"
|
|
25
25
|
},
|
|
26
26
|
"peerDependencies": {
|
|
27
|
-
"@itwin/core-bentley": "^4.0.0-dev.
|
|
28
|
-
"@itwin/core-common": "^4.0.0-dev.
|
|
29
|
-
"@itwin/core-geometry": "^4.0.0-dev.
|
|
27
|
+
"@itwin/core-bentley": "^4.0.0-dev.46",
|
|
28
|
+
"@itwin/core-common": "^4.0.0-dev.46",
|
|
29
|
+
"@itwin/core-geometry": "^4.0.0-dev.46",
|
|
30
30
|
"@opentelemetry/api": "^1.0.4"
|
|
31
31
|
},
|
|
32
32
|
"peerDependenciesMeta": {
|
|
@@ -39,12 +39,12 @@
|
|
|
39
39
|
"NOTE: All tools used by scripts in this package must be listed as devDependencies"
|
|
40
40
|
],
|
|
41
41
|
"devDependencies": {
|
|
42
|
-
"@itwin/build-tools": "4.0.0-dev.
|
|
43
|
-
"@itwin/core-bentley": "4.0.0-dev.
|
|
44
|
-
"@itwin/core-common": "4.0.0-dev.
|
|
45
|
-
"@itwin/core-geometry": "4.0.0-dev.
|
|
46
|
-
"@itwin/core-webpack-tools": "4.0.0-dev.
|
|
47
|
-
"@itwin/eslint-plugin": "
|
|
42
|
+
"@itwin/build-tools": "4.0.0-dev.46",
|
|
43
|
+
"@itwin/core-bentley": "4.0.0-dev.46",
|
|
44
|
+
"@itwin/core-common": "4.0.0-dev.46",
|
|
45
|
+
"@itwin/core-geometry": "4.0.0-dev.46",
|
|
46
|
+
"@itwin/core-webpack-tools": "4.0.0-dev.46",
|
|
47
|
+
"@itwin/eslint-plugin": "nightly",
|
|
48
48
|
"@opentelemetry/api": "1.0.4",
|
|
49
49
|
"@types/chai": "4.3.1",
|
|
50
50
|
"@types/chai-as-promised": "^7",
|
|
@@ -70,7 +70,7 @@
|
|
|
70
70
|
"sinon": "^9.0.2",
|
|
71
71
|
"source-map-loader": "^4.0.0",
|
|
72
72
|
"typescript": "~4.4.0",
|
|
73
|
-
"webpack": "^5.
|
|
73
|
+
"webpack": "^5.76.0"
|
|
74
74
|
},
|
|
75
75
|
"dependencies": {
|
|
76
76
|
"@azure/storage-blob": "^12.7.0",
|
|
@@ -78,7 +78,7 @@
|
|
|
78
78
|
"@itwin/object-storage-azure": "^1.5.0",
|
|
79
79
|
"@itwin/cloud-agnostic-core": "^1.5.0",
|
|
80
80
|
"@itwin/object-storage-core": "^1.5.0",
|
|
81
|
-
"@itwin/core-telemetry": "4.0.0-dev.
|
|
81
|
+
"@itwin/core-telemetry": "4.0.0-dev.46",
|
|
82
82
|
"form-data": "^2.3.2",
|
|
83
83
|
"fs-extra": "^8.1.0",
|
|
84
84
|
"inversify": "~5.0.1",
|