@fluidframework/driver-web-cache 2.0.0-internal.5.4.2 → 2.0.0-internal.6.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/dist/FluidCache.js +9 -13
- package/dist/FluidCache.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/lib/FluidCache.js +9 -13
- package/lib/FluidCache.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/package.json +6 -6
- package/src/packageVersion.ts +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# @fluidframework/driver-web-cache
|
|
2
2
|
|
|
3
|
+
## 2.0.0-internal.6.0.0
|
|
4
|
+
|
|
5
|
+
### Major Changes
|
|
6
|
+
|
|
7
|
+
- Upgraded typescript transpilation target to ES2020 [8abce8cdb4](https://github.com/microsoft/FluidFramework/commits/8abce8cdb4e2832fb6405fb44e393bef03d5648a)
|
|
8
|
+
|
|
9
|
+
Upgraded typescript transpilation target to ES2020. This is done in order to decrease the bundle sizes of Fluid Framework packages. This has provided size improvements across the board for ex. Loader, Driver, Runtime etc. Reduced bundle sizes helps to load lesser code in apps and hence also helps to improve the perf.If any app wants to target any older versions of browsers with which this target version is not compatible, then they can use packages like babel to transpile to a older target.
|
|
10
|
+
|
|
3
11
|
## 2.0.0-internal.5.4.0
|
|
4
12
|
|
|
5
13
|
Dependency updates only.
|
package/dist/FluidCache.js
CHANGED
|
@@ -15,22 +15,20 @@ const packageVersion_1 = require("./packageVersion");
|
|
|
15
15
|
*/
|
|
16
16
|
class FluidCache {
|
|
17
17
|
constructor(config) {
|
|
18
|
-
var _a;
|
|
19
18
|
this.closeDbImmediately = true;
|
|
20
19
|
this.dbReuseCount = -1;
|
|
21
20
|
this.logger = (0, telemetry_utils_1.createChildLogger)({ logger: config.logger });
|
|
22
21
|
this.partitionKey = config.partitionKey;
|
|
23
22
|
this.maxCacheItemAge = config.maxCacheItemAge;
|
|
24
|
-
this.closeDbAfterMs =
|
|
23
|
+
this.closeDbAfterMs = config.closeDbAfterMs ?? 0;
|
|
25
24
|
if (this.closeDbAfterMs > 0) {
|
|
26
25
|
this.closeDbImmediately = false;
|
|
27
26
|
}
|
|
28
27
|
(0, scheduleIdleTask_1.scheduleIdleTask)(async () => {
|
|
29
|
-
var _a;
|
|
30
28
|
// Log how much storage space is currently being used by indexed db.
|
|
31
29
|
// NOTE: This API is not supported in all browsers and it doesn't let you see the size of a specific DB.
|
|
32
30
|
// Exception added when eslint rule was added, this should be revisited when modifying this code
|
|
33
|
-
if (
|
|
31
|
+
if (navigator.storage?.estimate) {
|
|
34
32
|
const estimate = await navigator.storage.estimate();
|
|
35
33
|
// Some browsers have a usageDetails property that will tell you
|
|
36
34
|
// more detailed information on how the storage is being used
|
|
@@ -68,7 +66,7 @@ class FluidCache {
|
|
|
68
66
|
}, error);
|
|
69
67
|
}
|
|
70
68
|
finally {
|
|
71
|
-
db
|
|
69
|
+
db?.close();
|
|
72
70
|
}
|
|
73
71
|
});
|
|
74
72
|
}
|
|
@@ -90,8 +88,7 @@ class FluidCache {
|
|
|
90
88
|
}
|
|
91
89
|
// Need to close the db on version change if opened.
|
|
92
90
|
this.db.onversionchange = (ev) => {
|
|
93
|
-
|
|
94
|
-
(_a = this.db) === null || _a === void 0 ? void 0 : _a.close();
|
|
91
|
+
this.db?.close();
|
|
95
92
|
this.db = undefined;
|
|
96
93
|
clearTimeout(this.dbCloseTimer);
|
|
97
94
|
this.dbCloseTimer = undefined;
|
|
@@ -104,8 +101,7 @@ class FluidCache {
|
|
|
104
101
|
// Schedule db close after this.closeDbAfterMs.
|
|
105
102
|
(0, common_utils_1.assert)(this.dbCloseTimer === undefined, 0x6c6 /* timer should not be set yet!! */);
|
|
106
103
|
this.dbCloseTimer = setTimeout(() => {
|
|
107
|
-
|
|
108
|
-
(_a = this.db) === null || _a === void 0 ? void 0 : _a.close();
|
|
104
|
+
this.db?.close();
|
|
109
105
|
this.db = undefined;
|
|
110
106
|
this.dbCloseTimer = undefined;
|
|
111
107
|
}, this.closeDbAfterMs);
|
|
@@ -116,7 +112,7 @@ class FluidCache {
|
|
|
116
112
|
}
|
|
117
113
|
closeDb(db) {
|
|
118
114
|
if (this.closeDbImmediately) {
|
|
119
|
-
db
|
|
115
|
+
db?.close();
|
|
120
116
|
}
|
|
121
117
|
}
|
|
122
118
|
async removeEntries(file) {
|
|
@@ -147,13 +143,13 @@ class FluidCache {
|
|
|
147
143
|
cacheHit: cachedItem !== undefined,
|
|
148
144
|
type: cacheEntry.type,
|
|
149
145
|
duration: performance.now() - startTime,
|
|
150
|
-
dbOpenPerf: cachedItem
|
|
146
|
+
dbOpenPerf: cachedItem?.dbOpenPerf,
|
|
151
147
|
dbReuseCount: this.dbReuseCount,
|
|
152
148
|
pkgVersion: packageVersion_1.pkgVersion,
|
|
153
149
|
});
|
|
154
150
|
// Value will contain metadata like the expiry time, we just want to return the object we were asked to cache
|
|
155
151
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
156
|
-
return cachedItem
|
|
152
|
+
return cachedItem?.cachedObject;
|
|
157
153
|
}
|
|
158
154
|
async getItemFromCache(cacheEntry) {
|
|
159
155
|
let db;
|
|
@@ -184,7 +180,7 @@ class FluidCache {
|
|
|
184
180
|
return undefined;
|
|
185
181
|
}
|
|
186
182
|
this.closeDb(db);
|
|
187
|
-
return
|
|
183
|
+
return { ...value, dbOpenPerf };
|
|
188
184
|
}
|
|
189
185
|
catch (error) {
|
|
190
186
|
// We can fail to open the db for a variety of reasons,
|
package/dist/FluidCache.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FluidCache.js","sourceRoot":"","sources":["../src/FluidCache.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { IDBPDatabase } from \"idb\";\nimport { assert } from \"@fluidframework/common-utils\";\nimport { IPersistedCache, ICacheEntry, IFileEntry } from \"@fluidframework/odsp-driver-definitions\";\nimport { ITelemetryBaseLogger } from \"@fluidframework/core-interfaces\";\nimport { ITelemetryLoggerExt, createChildLogger } from \"@fluidframework/telemetry-utils\";\nimport { scheduleIdleTask } from \"./scheduleIdleTask\";\nimport {\n\tgetFluidCacheIndexedDbInstance,\n\tFluidCacheDBSchema,\n\tFluidDriverObjectStoreName,\n\tgetKeyForCacheEntry,\n} from \"./FluidCacheIndexedDb\";\nimport {\n\tFluidCacheErrorEvent,\n\tFluidCacheEventSubCategories,\n\tFluidCacheGenericEvent,\n} from \"./fluidCacheTelemetry\";\nimport { pkgVersion } from \"./packageVersion\";\n\n// Some browsers have a usageDetails property that will tell you more detailed information\n// on how the storage is being used\ninterface StorageQuotaUsageDetails {\n\tindexedDB: number | undefined;\n}\n\nexport interface FluidCacheConfig {\n\t/**\n\t * A string to specify what partition of the cache you wish to use (e.g. a user id).\n\t * Null can be used to explicity indicate no partitioning, and has been chosen\n\t * vs undefined so that it is clear this is an intentional choice by the caller.\n\t * A null value should only be used when the host can ensure that the cache is not able\n\t * to be shared with multiple users.\n\t */\n\t// eslint-disable-next-line @rushstack/no-new-null\n\tpartitionKey: string | null;\n\n\t/**\n\t * A logger that can be used to get insight into cache performance and errors\n\t */\n\tlogger?: ITelemetryBaseLogger;\n\n\t/**\n\t * A value in milliseconds that determines the maximum age of a cache entry to return.\n\t * If an entry exists in the cache, but is older than this value, the cached value will not be returned.\n\t */\n\tmaxCacheItemAge: number;\n\n\t/**\n\t * Each time db is opened, it will remain open for this much time. To improve perf, if this property is set as\n\t * any number greater than 0, then db will not be closed immediately after usage. This value is in milliseconds.\n\t */\n\tcloseDbAfterMs?: number;\n}\n\n/**\n * A cache that can be used by the Fluid ODSP driver to cache data for faster performance\n */\nexport class FluidCache implements IPersistedCache {\n\tprivate readonly logger: ITelemetryLoggerExt;\n\n\tprivate readonly partitionKey: string | null;\n\n\tprivate readonly maxCacheItemAge: number;\n\tprivate readonly closeDbImmediately: boolean = true;\n\tprivate readonly closeDbAfterMs: number;\n\tprivate db: IDBPDatabase<FluidCacheDBSchema> | undefined;\n\tprivate dbCloseTimer: ReturnType<typeof setTimeout> | undefined;\n\tprivate dbReuseCount: number = -1;\n\n\tconstructor(config: FluidCacheConfig) {\n\t\tthis.logger = createChildLogger({ logger: config.logger });\n\t\tthis.partitionKey = config.partitionKey;\n\t\tthis.maxCacheItemAge = config.maxCacheItemAge;\n\t\tthis.closeDbAfterMs = config.closeDbAfterMs ?? 0;\n\t\tif (this.closeDbAfterMs > 0) {\n\t\t\tthis.closeDbImmediately = false;\n\t\t}\n\n\t\tscheduleIdleTask(async () => {\n\t\t\t// Log how much storage space is currently being used by indexed db.\n\t\t\t// NOTE: This API is not supported in all browsers and it doesn't let you see the size of a specific DB.\n\t\t\t// Exception added when eslint rule was added, this should be revisited when modifying this code\n\t\t\tif (navigator.storage?.estimate) {\n\t\t\t\tconst estimate = await navigator.storage.estimate();\n\n\t\t\t\t// Some browsers have a usageDetails property that will tell you\n\t\t\t\t// more detailed information on how the storage is being used\n\t\t\t\tlet indexedDBSize: number | undefined;\n\t\t\t\tif (\"usageDetails\" in estimate) {\n\t\t\t\t\tindexedDBSize = ((estimate as any).usageDetails as StorageQuotaUsageDetails)\n\t\t\t\t\t\t.indexedDB;\n\t\t\t\t}\n\n\t\t\t\tthis.logger.sendTelemetryEvent({\n\t\t\t\t\teventName: FluidCacheGenericEvent.FluidCacheStorageInfo,\n\t\t\t\t\tsubCategory: FluidCacheEventSubCategories.FluidCache,\n\t\t\t\t\tquota: estimate.quota,\n\t\t\t\t\tusage: estimate.usage,\n\t\t\t\t\tindexedDBSize,\n\t\t\t\t\tpkgVersion,\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\n\t\tscheduleIdleTask(async () => {\n\t\t\tlet db: IDBPDatabase<FluidCacheDBSchema> | undefined;\n\n\t\t\t// Delete entries that have not been accessed recently to clean up space\n\t\t\ttry {\n\t\t\t\tdb = await getFluidCacheIndexedDbInstance(this.logger);\n\n\t\t\t\tconst transaction = db.transaction(FluidDriverObjectStoreName, \"readwrite\");\n\t\t\t\tconst index = transaction.store.index(\"createdTimeMs\");\n\t\t\t\t// Get items which were cached before the maxCacheItemAge.\n\t\t\t\tconst keysToDelete = await index.getAllKeys(\n\t\t\t\t\tIDBKeyRange.upperBound(new Date().getTime() - this.maxCacheItemAge),\n\t\t\t\t);\n\n\t\t\t\tawait Promise.all(keysToDelete.map((key) => transaction.store.delete(key)));\n\t\t\t\tawait transaction.done;\n\t\t\t} catch (error: any) {\n\t\t\t\tthis.logger.sendErrorEvent(\n\t\t\t\t\t{\n\t\t\t\t\t\teventName: FluidCacheErrorEvent.FluidCacheDeleteOldEntriesError,\n\t\t\t\t\t\tpkgVersion,\n\t\t\t\t\t},\n\t\t\t\t\terror,\n\t\t\t\t);\n\t\t\t} finally {\n\t\t\t\tdb?.close();\n\t\t\t}\n\t\t});\n\t}\n\n\tprivate async openDb() {\n\t\tif (this.closeDbImmediately) {\n\t\t\treturn getFluidCacheIndexedDbInstance(this.logger);\n\t\t}\n\t\tif (this.db === undefined) {\n\t\t\tconst dbInstance = await getFluidCacheIndexedDbInstance(this.logger);\n\t\t\tif (this.db === undefined) {\n\t\t\t\t// Reset the counter on first open.\n\t\t\t\tthis.dbReuseCount = -1;\n\t\t\t\tthis.db = dbInstance;\n\t\t\t} else {\n\t\t\t\tdbInstance.close();\n\t\t\t\tthis.dbReuseCount += 1;\n\t\t\t\treturn this.db;\n\t\t\t}\n\t\t\t// Need to close the db on version change if opened.\n\t\t\tthis.db.onversionchange = (ev) => {\n\t\t\t\tthis.db?.close();\n\t\t\t\tthis.db = undefined;\n\t\t\t\tclearTimeout(this.dbCloseTimer);\n\t\t\t\tthis.dbCloseTimer = undefined;\n\t\t\t};\n\t\t\tthis.db.addEventListener(\"close\", (ev) => {\n\t\t\t\tclearTimeout(this.dbCloseTimer);\n\t\t\t\tthis.dbCloseTimer = undefined;\n\t\t\t\tthis.db = undefined;\n\t\t\t});\n\t\t\t// Schedule db close after this.closeDbAfterMs.\n\t\t\tassert(this.dbCloseTimer === undefined, 0x6c6 /* timer should not be set yet!! */);\n\t\t\tthis.dbCloseTimer = setTimeout(() => {\n\t\t\t\tthis.db?.close();\n\t\t\t\tthis.db = undefined;\n\t\t\t\tthis.dbCloseTimer = undefined;\n\t\t\t}, this.closeDbAfterMs);\n\t\t}\n\t\tassert(this.db !== undefined, 0x6c7 /* db should be intialized by now */);\n\t\tthis.dbReuseCount += 1;\n\t\treturn this.db;\n\t}\n\n\tprivate closeDb(db?: IDBPDatabase<FluidCacheDBSchema>) {\n\t\tif (this.closeDbImmediately) {\n\t\t\tdb?.close();\n\t\t}\n\t}\n\n\tpublic async removeEntries(file: IFileEntry): Promise<void> {\n\t\tlet db: IDBPDatabase<FluidCacheDBSchema> | undefined;\n\t\ttry {\n\t\t\tdb = await this.openDb();\n\n\t\t\tconst transaction = db.transaction(FluidDriverObjectStoreName, \"readwrite\");\n\t\t\tconst index = transaction.store.index(\"fileId\");\n\n\t\t\tconst keysToDelete = await index.getAllKeys(file.docId);\n\n\t\t\tawait Promise.all(keysToDelete.map((key) => transaction.store.delete(key)));\n\t\t\tawait transaction.done;\n\t\t} catch (error: any) {\n\t\t\tthis.logger.sendErrorEvent(\n\t\t\t\t{\n\t\t\t\t\teventName: FluidCacheErrorEvent.FluidCacheDeleteOldEntriesError,\n\t\t\t\t\tpkgVersion,\n\t\t\t\t},\n\t\t\t\terror,\n\t\t\t);\n\t\t} finally {\n\t\t\tthis.closeDb(db);\n\t\t}\n\t}\n\n\tpublic async get(cacheEntry: ICacheEntry): Promise<any> {\n\t\tconst startTime = performance.now();\n\n\t\tconst cachedItem = await this.getItemFromCache(cacheEntry);\n\n\t\tthis.logger.sendPerformanceEvent({\n\t\t\teventName: \"FluidCacheAccess\",\n\t\t\tcacheHit: cachedItem !== undefined,\n\t\t\ttype: cacheEntry.type,\n\t\t\tduration: performance.now() - startTime,\n\t\t\tdbOpenPerf: cachedItem?.dbOpenPerf,\n\t\t\tdbReuseCount: this.dbReuseCount,\n\t\t\tpkgVersion,\n\t\t});\n\n\t\t// Value will contain metadata like the expiry time, we just want to return the object we were asked to cache\n\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-return\n\t\treturn cachedItem?.cachedObject;\n\t}\n\n\tprivate async getItemFromCache(cacheEntry: ICacheEntry) {\n\t\tlet db: IDBPDatabase<FluidCacheDBSchema> | undefined;\n\t\ttry {\n\t\t\tconst key = getKeyForCacheEntry(cacheEntry);\n\n\t\t\tconst dbOpenStartTime = performance.now();\n\t\t\tdb = await this.openDb();\n\t\t\tconst dbOpenPerf = performance.now() - dbOpenStartTime;\n\t\t\tconst value = await db.get(FluidDriverObjectStoreName, key);\n\n\t\t\tif (!value) {\n\t\t\t\tthis.closeDb(db);\n\t\t\t\treturn undefined;\n\t\t\t}\n\n\t\t\t// If the data does not come from the same partition, don't return it\n\t\t\tif (value.partitionKey !== this.partitionKey) {\n\t\t\t\tthis.logger.sendTelemetryEvent({\n\t\t\t\t\teventName: FluidCacheGenericEvent.FluidCachePartitionKeyMismatch,\n\t\t\t\t\tsubCategory: FluidCacheEventSubCategories.FluidCache,\n\t\t\t\t\tpkgVersion,\n\t\t\t\t});\n\n\t\t\t\tthis.closeDb(db);\n\t\t\t\treturn undefined;\n\t\t\t}\n\n\t\t\tconst currentTime = new Date().getTime();\n\n\t\t\t// If too much time has passed since this cache entry was used, we will also return undefined\n\t\t\tif (currentTime - value.createdTimeMs > this.maxCacheItemAge) {\n\t\t\t\tthis.closeDb(db);\n\t\t\t\treturn undefined;\n\t\t\t}\n\n\t\t\tthis.closeDb(db);\n\t\t\treturn { ...value, dbOpenPerf };\n\t\t} catch (error: any) {\n\t\t\t// We can fail to open the db for a variety of reasons,\n\t\t\t// such as the database version having upgraded underneath us. Return undefined in this case\n\t\t\tthis.logger.sendErrorEvent(\n\t\t\t\t{ eventName: FluidCacheErrorEvent.FluidCacheGetError, pkgVersion },\n\t\t\t\terror,\n\t\t\t);\n\t\t\tthis.closeDb(db);\n\t\t\treturn undefined;\n\t\t}\n\t}\n\n\tpublic async put(entry: ICacheEntry, value: any): Promise<void> {\n\t\tlet db: IDBPDatabase<FluidCacheDBSchema> | undefined;\n\t\ttry {\n\t\t\tdb = await this.openDb();\n\n\t\t\tconst currentTime = new Date().getTime();\n\n\t\t\tawait db.put(\n\t\t\t\tFluidDriverObjectStoreName,\n\t\t\t\t{\n\t\t\t\t\tcachedObject: value,\n\t\t\t\t\tfileId: entry.file.docId,\n\t\t\t\t\ttype: entry.type,\n\t\t\t\t\tcacheItemId: entry.key,\n\t\t\t\t\tpartitionKey: this.partitionKey,\n\t\t\t\t\tcreatedTimeMs: currentTime,\n\t\t\t\t\tlastAccessTimeMs: currentTime,\n\t\t\t\t},\n\t\t\t\tgetKeyForCacheEntry(entry),\n\t\t\t);\n\t\t\tthis.closeDb(db);\n\t\t} catch (error: any) {\n\t\t\t// We can fail to open the db for a variety of reasons,\n\t\t\t// such as the database version having upgraded underneath us\n\t\t\tthis.logger.sendErrorEvent(\n\t\t\t\t{ eventName: FluidCacheErrorEvent.FluidCachePutError, pkgVersion },\n\t\t\t\terror,\n\t\t\t);\n\t\t} finally {\n\t\t\tthis.closeDb(db);\n\t\t}\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"FluidCache.js","sourceRoot":"","sources":["../src/FluidCache.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { IDBPDatabase } from \"idb\";\nimport { assert } from \"@fluidframework/common-utils\";\nimport { IPersistedCache, ICacheEntry, IFileEntry } from \"@fluidframework/odsp-driver-definitions\";\nimport { ITelemetryBaseLogger } from \"@fluidframework/core-interfaces\";\nimport { ITelemetryLoggerExt, createChildLogger } from \"@fluidframework/telemetry-utils\";\nimport { scheduleIdleTask } from \"./scheduleIdleTask\";\nimport {\n\tgetFluidCacheIndexedDbInstance,\n\tFluidCacheDBSchema,\n\tFluidDriverObjectStoreName,\n\tgetKeyForCacheEntry,\n} from \"./FluidCacheIndexedDb\";\nimport {\n\tFluidCacheErrorEvent,\n\tFluidCacheEventSubCategories,\n\tFluidCacheGenericEvent,\n} from \"./fluidCacheTelemetry\";\nimport { pkgVersion } from \"./packageVersion\";\n\n// Some browsers have a usageDetails property that will tell you more detailed information\n// on how the storage is being used\ninterface StorageQuotaUsageDetails {\n\tindexedDB: number | undefined;\n}\n\nexport interface FluidCacheConfig {\n\t/**\n\t * A string to specify what partition of the cache you wish to use (e.g. a user id).\n\t * Null can be used to explicity indicate no partitioning, and has been chosen\n\t * vs undefined so that it is clear this is an intentional choice by the caller.\n\t * A null value should only be used when the host can ensure that the cache is not able\n\t * to be shared with multiple users.\n\t */\n\t// eslint-disable-next-line @rushstack/no-new-null\n\tpartitionKey: string | null;\n\n\t/**\n\t * A logger that can be used to get insight into cache performance and errors\n\t */\n\tlogger?: ITelemetryBaseLogger;\n\n\t/**\n\t * A value in milliseconds that determines the maximum age of a cache entry to return.\n\t * If an entry exists in the cache, but is older than this value, the cached value will not be returned.\n\t */\n\tmaxCacheItemAge: number;\n\n\t/**\n\t * Each time db is opened, it will remain open for this much time. To improve perf, if this property is set as\n\t * any number greater than 0, then db will not be closed immediately after usage. This value is in milliseconds.\n\t */\n\tcloseDbAfterMs?: number;\n}\n\n/**\n * A cache that can be used by the Fluid ODSP driver to cache data for faster performance\n */\nexport class FluidCache implements IPersistedCache {\n\tprivate readonly logger: ITelemetryLoggerExt;\n\n\tprivate readonly partitionKey: string | null;\n\n\tprivate readonly maxCacheItemAge: number;\n\tprivate readonly closeDbImmediately: boolean = true;\n\tprivate readonly closeDbAfterMs: number;\n\tprivate db: IDBPDatabase<FluidCacheDBSchema> | undefined;\n\tprivate dbCloseTimer: ReturnType<typeof setTimeout> | undefined;\n\tprivate dbReuseCount: number = -1;\n\n\tconstructor(config: FluidCacheConfig) {\n\t\tthis.logger = createChildLogger({ logger: config.logger });\n\t\tthis.partitionKey = config.partitionKey;\n\t\tthis.maxCacheItemAge = config.maxCacheItemAge;\n\t\tthis.closeDbAfterMs = config.closeDbAfterMs ?? 0;\n\t\tif (this.closeDbAfterMs > 0) {\n\t\t\tthis.closeDbImmediately = false;\n\t\t}\n\n\t\tscheduleIdleTask(async () => {\n\t\t\t// Log how much storage space is currently being used by indexed db.\n\t\t\t// NOTE: This API is not supported in all browsers and it doesn't let you see the size of a specific DB.\n\t\t\t// Exception added when eslint rule was added, this should be revisited when modifying this code\n\t\t\tif (navigator.storage?.estimate) {\n\t\t\t\tconst estimate = await navigator.storage.estimate();\n\n\t\t\t\t// Some browsers have a usageDetails property that will tell you\n\t\t\t\t// more detailed information on how the storage is being used\n\t\t\t\tlet indexedDBSize: number | undefined;\n\t\t\t\tif (\"usageDetails\" in estimate) {\n\t\t\t\t\tindexedDBSize = ((estimate as any).usageDetails as StorageQuotaUsageDetails)\n\t\t\t\t\t\t.indexedDB;\n\t\t\t\t}\n\n\t\t\t\tthis.logger.sendTelemetryEvent({\n\t\t\t\t\teventName: FluidCacheGenericEvent.FluidCacheStorageInfo,\n\t\t\t\t\tsubCategory: FluidCacheEventSubCategories.FluidCache,\n\t\t\t\t\tquota: estimate.quota,\n\t\t\t\t\tusage: estimate.usage,\n\t\t\t\t\tindexedDBSize,\n\t\t\t\t\tpkgVersion,\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\n\t\tscheduleIdleTask(async () => {\n\t\t\tlet db: IDBPDatabase<FluidCacheDBSchema> | undefined;\n\n\t\t\t// Delete entries that have not been accessed recently to clean up space\n\t\t\ttry {\n\t\t\t\tdb = await getFluidCacheIndexedDbInstance(this.logger);\n\n\t\t\t\tconst transaction = db.transaction(FluidDriverObjectStoreName, \"readwrite\");\n\t\t\t\tconst index = transaction.store.index(\"createdTimeMs\");\n\t\t\t\t// Get items which were cached before the maxCacheItemAge.\n\t\t\t\tconst keysToDelete = await index.getAllKeys(\n\t\t\t\t\tIDBKeyRange.upperBound(new Date().getTime() - this.maxCacheItemAge),\n\t\t\t\t);\n\n\t\t\t\tawait Promise.all(keysToDelete.map((key) => transaction.store.delete(key)));\n\t\t\t\tawait transaction.done;\n\t\t\t} catch (error: any) {\n\t\t\t\tthis.logger.sendErrorEvent(\n\t\t\t\t\t{\n\t\t\t\t\t\teventName: FluidCacheErrorEvent.FluidCacheDeleteOldEntriesError,\n\t\t\t\t\t\tpkgVersion,\n\t\t\t\t\t},\n\t\t\t\t\terror,\n\t\t\t\t);\n\t\t\t} finally {\n\t\t\t\tdb?.close();\n\t\t\t}\n\t\t});\n\t}\n\n\tprivate async openDb() {\n\t\tif (this.closeDbImmediately) {\n\t\t\treturn getFluidCacheIndexedDbInstance(this.logger);\n\t\t}\n\t\tif (this.db === undefined) {\n\t\t\tconst dbInstance = await getFluidCacheIndexedDbInstance(this.logger);\n\t\t\tif (this.db === undefined) {\n\t\t\t\t// Reset the counter on first open.\n\t\t\t\tthis.dbReuseCount = -1;\n\t\t\t\tthis.db = dbInstance;\n\t\t\t} else {\n\t\t\t\tdbInstance.close();\n\t\t\t\tthis.dbReuseCount += 1;\n\t\t\t\treturn this.db;\n\t\t\t}\n\t\t\t// Need to close the db on version change if opened.\n\t\t\tthis.db.onversionchange = (ev) => {\n\t\t\t\tthis.db?.close();\n\t\t\t\tthis.db = undefined;\n\t\t\t\tclearTimeout(this.dbCloseTimer);\n\t\t\t\tthis.dbCloseTimer = undefined;\n\t\t\t};\n\t\t\tthis.db.addEventListener(\"close\", (ev) => {\n\t\t\t\tclearTimeout(this.dbCloseTimer);\n\t\t\t\tthis.dbCloseTimer = undefined;\n\t\t\t\tthis.db = undefined;\n\t\t\t});\n\t\t\t// Schedule db close after this.closeDbAfterMs.\n\t\t\tassert(this.dbCloseTimer === undefined, 0x6c6 /* timer should not be set yet!! */);\n\t\t\tthis.dbCloseTimer = setTimeout(() => {\n\t\t\t\tthis.db?.close();\n\t\t\t\tthis.db = undefined;\n\t\t\t\tthis.dbCloseTimer = undefined;\n\t\t\t}, this.closeDbAfterMs);\n\t\t}\n\t\tassert(this.db !== undefined, 0x6c7 /* db should be intialized by now */);\n\t\tthis.dbReuseCount += 1;\n\t\treturn this.db;\n\t}\n\n\tprivate closeDb(db?: IDBPDatabase<FluidCacheDBSchema>) {\n\t\tif (this.closeDbImmediately) {\n\t\t\tdb?.close();\n\t\t}\n\t}\n\n\tpublic async removeEntries(file: IFileEntry): Promise<void> {\n\t\tlet db: IDBPDatabase<FluidCacheDBSchema> | undefined;\n\t\ttry {\n\t\t\tdb = await this.openDb();\n\n\t\t\tconst transaction = db.transaction(FluidDriverObjectStoreName, \"readwrite\");\n\t\t\tconst index = transaction.store.index(\"fileId\");\n\n\t\t\tconst keysToDelete = await index.getAllKeys(file.docId);\n\n\t\t\tawait Promise.all(keysToDelete.map((key) => transaction.store.delete(key)));\n\t\t\tawait transaction.done;\n\t\t} catch (error: any) {\n\t\t\tthis.logger.sendErrorEvent(\n\t\t\t\t{\n\t\t\t\t\teventName: FluidCacheErrorEvent.FluidCacheDeleteOldEntriesError,\n\t\t\t\t\tpkgVersion,\n\t\t\t\t},\n\t\t\t\terror,\n\t\t\t);\n\t\t} finally {\n\t\t\tthis.closeDb(db);\n\t\t}\n\t}\n\n\tpublic async get(cacheEntry: ICacheEntry): Promise<any> {\n\t\tconst startTime = performance.now();\n\n\t\tconst cachedItem = await this.getItemFromCache(cacheEntry);\n\n\t\tthis.logger.sendPerformanceEvent({\n\t\t\teventName: \"FluidCacheAccess\",\n\t\t\tcacheHit: cachedItem !== undefined,\n\t\t\ttype: cacheEntry.type,\n\t\t\tduration: performance.now() - startTime,\n\t\t\tdbOpenPerf: cachedItem?.dbOpenPerf,\n\t\t\tdbReuseCount: this.dbReuseCount,\n\t\t\tpkgVersion,\n\t\t});\n\n\t\t// Value will contain metadata like the expiry time, we just want to return the object we were asked to cache\n\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-return\n\t\treturn cachedItem?.cachedObject;\n\t}\n\n\tprivate async getItemFromCache(cacheEntry: ICacheEntry) {\n\t\tlet db: IDBPDatabase<FluidCacheDBSchema> | undefined;\n\t\ttry {\n\t\t\tconst key = getKeyForCacheEntry(cacheEntry);\n\n\t\t\tconst dbOpenStartTime = performance.now();\n\t\t\tdb = await this.openDb();\n\t\t\tconst dbOpenPerf = performance.now() - dbOpenStartTime;\n\t\t\tconst value = await db.get(FluidDriverObjectStoreName, key);\n\n\t\t\tif (!value) {\n\t\t\t\tthis.closeDb(db);\n\t\t\t\treturn undefined;\n\t\t\t}\n\n\t\t\t// If the data does not come from the same partition, don't return it\n\t\t\tif (value.partitionKey !== this.partitionKey) {\n\t\t\t\tthis.logger.sendTelemetryEvent({\n\t\t\t\t\teventName: FluidCacheGenericEvent.FluidCachePartitionKeyMismatch,\n\t\t\t\t\tsubCategory: FluidCacheEventSubCategories.FluidCache,\n\t\t\t\t\tpkgVersion,\n\t\t\t\t});\n\n\t\t\t\tthis.closeDb(db);\n\t\t\t\treturn undefined;\n\t\t\t}\n\n\t\t\tconst currentTime = new Date().getTime();\n\n\t\t\t// If too much time has passed since this cache entry was used, we will also return undefined\n\t\t\tif (currentTime - value.createdTimeMs > this.maxCacheItemAge) {\n\t\t\t\tthis.closeDb(db);\n\t\t\t\treturn undefined;\n\t\t\t}\n\n\t\t\tthis.closeDb(db);\n\t\t\treturn { ...value, dbOpenPerf };\n\t\t} catch (error: any) {\n\t\t\t// We can fail to open the db for a variety of reasons,\n\t\t\t// such as the database version having upgraded underneath us. Return undefined in this case\n\t\t\tthis.logger.sendErrorEvent(\n\t\t\t\t{ eventName: FluidCacheErrorEvent.FluidCacheGetError, pkgVersion },\n\t\t\t\terror,\n\t\t\t);\n\t\t\tthis.closeDb(db);\n\t\t\treturn undefined;\n\t\t}\n\t}\n\n\tpublic async put(entry: ICacheEntry, value: any): Promise<void> {\n\t\tlet db: IDBPDatabase<FluidCacheDBSchema> | undefined;\n\t\ttry {\n\t\t\tdb = await this.openDb();\n\n\t\t\tconst currentTime = new Date().getTime();\n\n\t\t\tawait db.put(\n\t\t\t\tFluidDriverObjectStoreName,\n\t\t\t\t{\n\t\t\t\t\tcachedObject: value,\n\t\t\t\t\tfileId: entry.file.docId,\n\t\t\t\t\ttype: entry.type,\n\t\t\t\t\tcacheItemId: entry.key,\n\t\t\t\t\tpartitionKey: this.partitionKey,\n\t\t\t\t\tcreatedTimeMs: currentTime,\n\t\t\t\t\tlastAccessTimeMs: currentTime,\n\t\t\t\t},\n\t\t\t\tgetKeyForCacheEntry(entry),\n\t\t\t);\n\t\t\tthis.closeDb(db);\n\t\t} catch (error: any) {\n\t\t\t// We can fail to open the db for a variety of reasons,\n\t\t\t// such as the database version having upgraded underneath us\n\t\t\tthis.logger.sendErrorEvent(\n\t\t\t\t{ eventName: FluidCacheErrorEvent.FluidCachePutError, pkgVersion },\n\t\t\t\terror,\n\t\t\t);\n\t\t} finally {\n\t\t\tthis.closeDb(db);\n\t\t}\n\t}\n}\n"]}
|
package/dist/packageVersion.d.ts
CHANGED
|
@@ -5,5 +5,5 @@
|
|
|
5
5
|
* THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY
|
|
6
6
|
*/
|
|
7
7
|
export declare const pkgName = "@fluidframework/driver-web-cache";
|
|
8
|
-
export declare const pkgVersion = "2.0.0-internal.
|
|
8
|
+
export declare const pkgVersion = "2.0.0-internal.6.0.1";
|
|
9
9
|
//# sourceMappingURL=packageVersion.d.ts.map
|
package/dist/packageVersion.js
CHANGED
|
@@ -8,5 +8,5 @@
|
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
9
|
exports.pkgVersion = exports.pkgName = void 0;
|
|
10
10
|
exports.pkgName = "@fluidframework/driver-web-cache";
|
|
11
|
-
exports.pkgVersion = "2.0.0-internal.
|
|
11
|
+
exports.pkgVersion = "2.0.0-internal.6.0.1";
|
|
12
12
|
//# sourceMappingURL=packageVersion.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;AAEU,QAAA,OAAO,GAAG,kCAAkC,CAAC;AAC7C,QAAA,UAAU,GAAG,sBAAsB,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n *\n * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY\n */\n\nexport const pkgName = \"@fluidframework/driver-web-cache\";\nexport const pkgVersion = \"2.0.0-internal.
|
|
1
|
+
{"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;AAEU,QAAA,OAAO,GAAG,kCAAkC,CAAC;AAC7C,QAAA,UAAU,GAAG,sBAAsB,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n *\n * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY\n */\n\nexport const pkgName = \"@fluidframework/driver-web-cache\";\nexport const pkgVersion = \"2.0.0-internal.6.0.1\";\n"]}
|
package/lib/FluidCache.js
CHANGED
|
@@ -12,22 +12,20 @@ import { pkgVersion } from "./packageVersion";
|
|
|
12
12
|
*/
|
|
13
13
|
export class FluidCache {
|
|
14
14
|
constructor(config) {
|
|
15
|
-
var _a;
|
|
16
15
|
this.closeDbImmediately = true;
|
|
17
16
|
this.dbReuseCount = -1;
|
|
18
17
|
this.logger = createChildLogger({ logger: config.logger });
|
|
19
18
|
this.partitionKey = config.partitionKey;
|
|
20
19
|
this.maxCacheItemAge = config.maxCacheItemAge;
|
|
21
|
-
this.closeDbAfterMs =
|
|
20
|
+
this.closeDbAfterMs = config.closeDbAfterMs ?? 0;
|
|
22
21
|
if (this.closeDbAfterMs > 0) {
|
|
23
22
|
this.closeDbImmediately = false;
|
|
24
23
|
}
|
|
25
24
|
scheduleIdleTask(async () => {
|
|
26
|
-
var _a;
|
|
27
25
|
// Log how much storage space is currently being used by indexed db.
|
|
28
26
|
// NOTE: This API is not supported in all browsers and it doesn't let you see the size of a specific DB.
|
|
29
27
|
// Exception added when eslint rule was added, this should be revisited when modifying this code
|
|
30
|
-
if (
|
|
28
|
+
if (navigator.storage?.estimate) {
|
|
31
29
|
const estimate = await navigator.storage.estimate();
|
|
32
30
|
// Some browsers have a usageDetails property that will tell you
|
|
33
31
|
// more detailed information on how the storage is being used
|
|
@@ -65,7 +63,7 @@ export class FluidCache {
|
|
|
65
63
|
}, error);
|
|
66
64
|
}
|
|
67
65
|
finally {
|
|
68
|
-
db
|
|
66
|
+
db?.close();
|
|
69
67
|
}
|
|
70
68
|
});
|
|
71
69
|
}
|
|
@@ -87,8 +85,7 @@ export class FluidCache {
|
|
|
87
85
|
}
|
|
88
86
|
// Need to close the db on version change if opened.
|
|
89
87
|
this.db.onversionchange = (ev) => {
|
|
90
|
-
|
|
91
|
-
(_a = this.db) === null || _a === void 0 ? void 0 : _a.close();
|
|
88
|
+
this.db?.close();
|
|
92
89
|
this.db = undefined;
|
|
93
90
|
clearTimeout(this.dbCloseTimer);
|
|
94
91
|
this.dbCloseTimer = undefined;
|
|
@@ -101,8 +98,7 @@ export class FluidCache {
|
|
|
101
98
|
// Schedule db close after this.closeDbAfterMs.
|
|
102
99
|
assert(this.dbCloseTimer === undefined, 0x6c6 /* timer should not be set yet!! */);
|
|
103
100
|
this.dbCloseTimer = setTimeout(() => {
|
|
104
|
-
|
|
105
|
-
(_a = this.db) === null || _a === void 0 ? void 0 : _a.close();
|
|
101
|
+
this.db?.close();
|
|
106
102
|
this.db = undefined;
|
|
107
103
|
this.dbCloseTimer = undefined;
|
|
108
104
|
}, this.closeDbAfterMs);
|
|
@@ -113,7 +109,7 @@ export class FluidCache {
|
|
|
113
109
|
}
|
|
114
110
|
closeDb(db) {
|
|
115
111
|
if (this.closeDbImmediately) {
|
|
116
|
-
db
|
|
112
|
+
db?.close();
|
|
117
113
|
}
|
|
118
114
|
}
|
|
119
115
|
async removeEntries(file) {
|
|
@@ -144,13 +140,13 @@ export class FluidCache {
|
|
|
144
140
|
cacheHit: cachedItem !== undefined,
|
|
145
141
|
type: cacheEntry.type,
|
|
146
142
|
duration: performance.now() - startTime,
|
|
147
|
-
dbOpenPerf: cachedItem
|
|
143
|
+
dbOpenPerf: cachedItem?.dbOpenPerf,
|
|
148
144
|
dbReuseCount: this.dbReuseCount,
|
|
149
145
|
pkgVersion,
|
|
150
146
|
});
|
|
151
147
|
// Value will contain metadata like the expiry time, we just want to return the object we were asked to cache
|
|
152
148
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
153
|
-
return cachedItem
|
|
149
|
+
return cachedItem?.cachedObject;
|
|
154
150
|
}
|
|
155
151
|
async getItemFromCache(cacheEntry) {
|
|
156
152
|
let db;
|
|
@@ -181,7 +177,7 @@ export class FluidCache {
|
|
|
181
177
|
return undefined;
|
|
182
178
|
}
|
|
183
179
|
this.closeDb(db);
|
|
184
|
-
return
|
|
180
|
+
return { ...value, dbOpenPerf };
|
|
185
181
|
}
|
|
186
182
|
catch (error) {
|
|
187
183
|
// We can fail to open the db for a variety of reasons,
|
package/lib/FluidCache.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FluidCache.js","sourceRoot":"","sources":["../src/FluidCache.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { IDBPDatabase } from \"idb\";\nimport { assert } from \"@fluidframework/common-utils\";\nimport { IPersistedCache, ICacheEntry, IFileEntry } from \"@fluidframework/odsp-driver-definitions\";\nimport { ITelemetryBaseLogger } from \"@fluidframework/core-interfaces\";\nimport { ITelemetryLoggerExt, createChildLogger } from \"@fluidframework/telemetry-utils\";\nimport { scheduleIdleTask } from \"./scheduleIdleTask\";\nimport {\n\tgetFluidCacheIndexedDbInstance,\n\tFluidCacheDBSchema,\n\tFluidDriverObjectStoreName,\n\tgetKeyForCacheEntry,\n} from \"./FluidCacheIndexedDb\";\nimport {\n\tFluidCacheErrorEvent,\n\tFluidCacheEventSubCategories,\n\tFluidCacheGenericEvent,\n} from \"./fluidCacheTelemetry\";\nimport { pkgVersion } from \"./packageVersion\";\n\n// Some browsers have a usageDetails property that will tell you more detailed information\n// on how the storage is being used\ninterface StorageQuotaUsageDetails {\n\tindexedDB: number | undefined;\n}\n\nexport interface FluidCacheConfig {\n\t/**\n\t * A string to specify what partition of the cache you wish to use (e.g. a user id).\n\t * Null can be used to explicity indicate no partitioning, and has been chosen\n\t * vs undefined so that it is clear this is an intentional choice by the caller.\n\t * A null value should only be used when the host can ensure that the cache is not able\n\t * to be shared with multiple users.\n\t */\n\t// eslint-disable-next-line @rushstack/no-new-null\n\tpartitionKey: string | null;\n\n\t/**\n\t * A logger that can be used to get insight into cache performance and errors\n\t */\n\tlogger?: ITelemetryBaseLogger;\n\n\t/**\n\t * A value in milliseconds that determines the maximum age of a cache entry to return.\n\t * If an entry exists in the cache, but is older than this value, the cached value will not be returned.\n\t */\n\tmaxCacheItemAge: number;\n\n\t/**\n\t * Each time db is opened, it will remain open for this much time. To improve perf, if this property is set as\n\t * any number greater than 0, then db will not be closed immediately after usage. This value is in milliseconds.\n\t */\n\tcloseDbAfterMs?: number;\n}\n\n/**\n * A cache that can be used by the Fluid ODSP driver to cache data for faster performance\n */\nexport class FluidCache implements IPersistedCache {\n\tprivate readonly logger: ITelemetryLoggerExt;\n\n\tprivate readonly partitionKey: string | null;\n\n\tprivate readonly maxCacheItemAge: number;\n\tprivate readonly closeDbImmediately: boolean = true;\n\tprivate readonly closeDbAfterMs: number;\n\tprivate db: IDBPDatabase<FluidCacheDBSchema> | undefined;\n\tprivate dbCloseTimer: ReturnType<typeof setTimeout> | undefined;\n\tprivate dbReuseCount: number = -1;\n\n\tconstructor(config: FluidCacheConfig) {\n\t\tthis.logger = createChildLogger({ logger: config.logger });\n\t\tthis.partitionKey = config.partitionKey;\n\t\tthis.maxCacheItemAge = config.maxCacheItemAge;\n\t\tthis.closeDbAfterMs = config.closeDbAfterMs ?? 0;\n\t\tif (this.closeDbAfterMs > 0) {\n\t\t\tthis.closeDbImmediately = false;\n\t\t}\n\n\t\tscheduleIdleTask(async () => {\n\t\t\t// Log how much storage space is currently being used by indexed db.\n\t\t\t// NOTE: This API is not supported in all browsers and it doesn't let you see the size of a specific DB.\n\t\t\t// Exception added when eslint rule was added, this should be revisited when modifying this code\n\t\t\tif (navigator.storage?.estimate) {\n\t\t\t\tconst estimate = await navigator.storage.estimate();\n\n\t\t\t\t// Some browsers have a usageDetails property that will tell you\n\t\t\t\t// more detailed information on how the storage is being used\n\t\t\t\tlet indexedDBSize: number | undefined;\n\t\t\t\tif (\"usageDetails\" in estimate) {\n\t\t\t\t\tindexedDBSize = ((estimate as any).usageDetails as StorageQuotaUsageDetails)\n\t\t\t\t\t\t.indexedDB;\n\t\t\t\t}\n\n\t\t\t\tthis.logger.sendTelemetryEvent({\n\t\t\t\t\teventName: FluidCacheGenericEvent.FluidCacheStorageInfo,\n\t\t\t\t\tsubCategory: FluidCacheEventSubCategories.FluidCache,\n\t\t\t\t\tquota: estimate.quota,\n\t\t\t\t\tusage: estimate.usage,\n\t\t\t\t\tindexedDBSize,\n\t\t\t\t\tpkgVersion,\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\n\t\tscheduleIdleTask(async () => {\n\t\t\tlet db: IDBPDatabase<FluidCacheDBSchema> | undefined;\n\n\t\t\t// Delete entries that have not been accessed recently to clean up space\n\t\t\ttry {\n\t\t\t\tdb = await getFluidCacheIndexedDbInstance(this.logger);\n\n\t\t\t\tconst transaction = db.transaction(FluidDriverObjectStoreName, \"readwrite\");\n\t\t\t\tconst index = transaction.store.index(\"createdTimeMs\");\n\t\t\t\t// Get items which were cached before the maxCacheItemAge.\n\t\t\t\tconst keysToDelete = await index.getAllKeys(\n\t\t\t\t\tIDBKeyRange.upperBound(new Date().getTime() - this.maxCacheItemAge),\n\t\t\t\t);\n\n\t\t\t\tawait Promise.all(keysToDelete.map((key) => transaction.store.delete(key)));\n\t\t\t\tawait transaction.done;\n\t\t\t} catch (error: any) {\n\t\t\t\tthis.logger.sendErrorEvent(\n\t\t\t\t\t{\n\t\t\t\t\t\teventName: FluidCacheErrorEvent.FluidCacheDeleteOldEntriesError,\n\t\t\t\t\t\tpkgVersion,\n\t\t\t\t\t},\n\t\t\t\t\terror,\n\t\t\t\t);\n\t\t\t} finally {\n\t\t\t\tdb?.close();\n\t\t\t}\n\t\t});\n\t}\n\n\tprivate async openDb() {\n\t\tif (this.closeDbImmediately) {\n\t\t\treturn getFluidCacheIndexedDbInstance(this.logger);\n\t\t}\n\t\tif (this.db === undefined) {\n\t\t\tconst dbInstance = await getFluidCacheIndexedDbInstance(this.logger);\n\t\t\tif (this.db === undefined) {\n\t\t\t\t// Reset the counter on first open.\n\t\t\t\tthis.dbReuseCount = -1;\n\t\t\t\tthis.db = dbInstance;\n\t\t\t} else {\n\t\t\t\tdbInstance.close();\n\t\t\t\tthis.dbReuseCount += 1;\n\t\t\t\treturn this.db;\n\t\t\t}\n\t\t\t// Need to close the db on version change if opened.\n\t\t\tthis.db.onversionchange = (ev) => {\n\t\t\t\tthis.db?.close();\n\t\t\t\tthis.db = undefined;\n\t\t\t\tclearTimeout(this.dbCloseTimer);\n\t\t\t\tthis.dbCloseTimer = undefined;\n\t\t\t};\n\t\t\tthis.db.addEventListener(\"close\", (ev) => {\n\t\t\t\tclearTimeout(this.dbCloseTimer);\n\t\t\t\tthis.dbCloseTimer = undefined;\n\t\t\t\tthis.db = undefined;\n\t\t\t});\n\t\t\t// Schedule db close after this.closeDbAfterMs.\n\t\t\tassert(this.dbCloseTimer === undefined, 0x6c6 /* timer should not be set yet!! */);\n\t\t\tthis.dbCloseTimer = setTimeout(() => {\n\t\t\t\tthis.db?.close();\n\t\t\t\tthis.db = undefined;\n\t\t\t\tthis.dbCloseTimer = undefined;\n\t\t\t}, this.closeDbAfterMs);\n\t\t}\n\t\tassert(this.db !== undefined, 0x6c7 /* db should be intialized by now */);\n\t\tthis.dbReuseCount += 1;\n\t\treturn this.db;\n\t}\n\n\tprivate closeDb(db?: IDBPDatabase<FluidCacheDBSchema>) {\n\t\tif (this.closeDbImmediately) {\n\t\t\tdb?.close();\n\t\t}\n\t}\n\n\tpublic async removeEntries(file: IFileEntry): Promise<void> {\n\t\tlet db: IDBPDatabase<FluidCacheDBSchema> | undefined;\n\t\ttry {\n\t\t\tdb = await this.openDb();\n\n\t\t\tconst transaction = db.transaction(FluidDriverObjectStoreName, \"readwrite\");\n\t\t\tconst index = transaction.store.index(\"fileId\");\n\n\t\t\tconst keysToDelete = await index.getAllKeys(file.docId);\n\n\t\t\tawait Promise.all(keysToDelete.map((key) => transaction.store.delete(key)));\n\t\t\tawait transaction.done;\n\t\t} catch (error: any) {\n\t\t\tthis.logger.sendErrorEvent(\n\t\t\t\t{\n\t\t\t\t\teventName: FluidCacheErrorEvent.FluidCacheDeleteOldEntriesError,\n\t\t\t\t\tpkgVersion,\n\t\t\t\t},\n\t\t\t\terror,\n\t\t\t);\n\t\t} finally {\n\t\t\tthis.closeDb(db);\n\t\t}\n\t}\n\n\tpublic async get(cacheEntry: ICacheEntry): Promise<any> {\n\t\tconst startTime = performance.now();\n\n\t\tconst cachedItem = await this.getItemFromCache(cacheEntry);\n\n\t\tthis.logger.sendPerformanceEvent({\n\t\t\teventName: \"FluidCacheAccess\",\n\t\t\tcacheHit: cachedItem !== undefined,\n\t\t\ttype: cacheEntry.type,\n\t\t\tduration: performance.now() - startTime,\n\t\t\tdbOpenPerf: cachedItem?.dbOpenPerf,\n\t\t\tdbReuseCount: this.dbReuseCount,\n\t\t\tpkgVersion,\n\t\t});\n\n\t\t// Value will contain metadata like the expiry time, we just want to return the object we were asked to cache\n\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-return\n\t\treturn cachedItem?.cachedObject;\n\t}\n\n\tprivate async getItemFromCache(cacheEntry: ICacheEntry) {\n\t\tlet db: IDBPDatabase<FluidCacheDBSchema> | undefined;\n\t\ttry {\n\t\t\tconst key = getKeyForCacheEntry(cacheEntry);\n\n\t\t\tconst dbOpenStartTime = performance.now();\n\t\t\tdb = await this.openDb();\n\t\t\tconst dbOpenPerf = performance.now() - dbOpenStartTime;\n\t\t\tconst value = await db.get(FluidDriverObjectStoreName, key);\n\n\t\t\tif (!value) {\n\t\t\t\tthis.closeDb(db);\n\t\t\t\treturn undefined;\n\t\t\t}\n\n\t\t\t// If the data does not come from the same partition, don't return it\n\t\t\tif (value.partitionKey !== this.partitionKey) {\n\t\t\t\tthis.logger.sendTelemetryEvent({\n\t\t\t\t\teventName: FluidCacheGenericEvent.FluidCachePartitionKeyMismatch,\n\t\t\t\t\tsubCategory: FluidCacheEventSubCategories.FluidCache,\n\t\t\t\t\tpkgVersion,\n\t\t\t\t});\n\n\t\t\t\tthis.closeDb(db);\n\t\t\t\treturn undefined;\n\t\t\t}\n\n\t\t\tconst currentTime = new Date().getTime();\n\n\t\t\t// If too much time has passed since this cache entry was used, we will also return undefined\n\t\t\tif (currentTime - value.createdTimeMs > this.maxCacheItemAge) {\n\t\t\t\tthis.closeDb(db);\n\t\t\t\treturn undefined;\n\t\t\t}\n\n\t\t\tthis.closeDb(db);\n\t\t\treturn { ...value, dbOpenPerf };\n\t\t} catch (error: any) {\n\t\t\t// We can fail to open the db for a variety of reasons,\n\t\t\t// such as the database version having upgraded underneath us. Return undefined in this case\n\t\t\tthis.logger.sendErrorEvent(\n\t\t\t\t{ eventName: FluidCacheErrorEvent.FluidCacheGetError, pkgVersion },\n\t\t\t\terror,\n\t\t\t);\n\t\t\tthis.closeDb(db);\n\t\t\treturn undefined;\n\t\t}\n\t}\n\n\tpublic async put(entry: ICacheEntry, value: any): Promise<void> {\n\t\tlet db: IDBPDatabase<FluidCacheDBSchema> | undefined;\n\t\ttry {\n\t\t\tdb = await this.openDb();\n\n\t\t\tconst currentTime = new Date().getTime();\n\n\t\t\tawait db.put(\n\t\t\t\tFluidDriverObjectStoreName,\n\t\t\t\t{\n\t\t\t\t\tcachedObject: value,\n\t\t\t\t\tfileId: entry.file.docId,\n\t\t\t\t\ttype: entry.type,\n\t\t\t\t\tcacheItemId: entry.key,\n\t\t\t\t\tpartitionKey: this.partitionKey,\n\t\t\t\t\tcreatedTimeMs: currentTime,\n\t\t\t\t\tlastAccessTimeMs: currentTime,\n\t\t\t\t},\n\t\t\t\tgetKeyForCacheEntry(entry),\n\t\t\t);\n\t\t\tthis.closeDb(db);\n\t\t} catch (error: any) {\n\t\t\t// We can fail to open the db for a variety of reasons,\n\t\t\t// such as the database version having upgraded underneath us\n\t\t\tthis.logger.sendErrorEvent(\n\t\t\t\t{ eventName: FluidCacheErrorEvent.FluidCachePutError, pkgVersion },\n\t\t\t\terror,\n\t\t\t);\n\t\t} finally {\n\t\t\tthis.closeDb(db);\n\t\t}\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"FluidCache.js","sourceRoot":"","sources":["../src/FluidCache.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { IDBPDatabase } from \"idb\";\nimport { assert } from \"@fluidframework/common-utils\";\nimport { IPersistedCache, ICacheEntry, IFileEntry } from \"@fluidframework/odsp-driver-definitions\";\nimport { ITelemetryBaseLogger } from \"@fluidframework/core-interfaces\";\nimport { ITelemetryLoggerExt, createChildLogger } from \"@fluidframework/telemetry-utils\";\nimport { scheduleIdleTask } from \"./scheduleIdleTask\";\nimport {\n\tgetFluidCacheIndexedDbInstance,\n\tFluidCacheDBSchema,\n\tFluidDriverObjectStoreName,\n\tgetKeyForCacheEntry,\n} from \"./FluidCacheIndexedDb\";\nimport {\n\tFluidCacheErrorEvent,\n\tFluidCacheEventSubCategories,\n\tFluidCacheGenericEvent,\n} from \"./fluidCacheTelemetry\";\nimport { pkgVersion } from \"./packageVersion\";\n\n// Some browsers have a usageDetails property that will tell you more detailed information\n// on how the storage is being used\ninterface StorageQuotaUsageDetails {\n\tindexedDB: number | undefined;\n}\n\nexport interface FluidCacheConfig {\n\t/**\n\t * A string to specify what partition of the cache you wish to use (e.g. a user id).\n\t * Null can be used to explicity indicate no partitioning, and has been chosen\n\t * vs undefined so that it is clear this is an intentional choice by the caller.\n\t * A null value should only be used when the host can ensure that the cache is not able\n\t * to be shared with multiple users.\n\t */\n\t// eslint-disable-next-line @rushstack/no-new-null\n\tpartitionKey: string | null;\n\n\t/**\n\t * A logger that can be used to get insight into cache performance and errors\n\t */\n\tlogger?: ITelemetryBaseLogger;\n\n\t/**\n\t * A value in milliseconds that determines the maximum age of a cache entry to return.\n\t * If an entry exists in the cache, but is older than this value, the cached value will not be returned.\n\t */\n\tmaxCacheItemAge: number;\n\n\t/**\n\t * Each time db is opened, it will remain open for this much time. To improve perf, if this property is set as\n\t * any number greater than 0, then db will not be closed immediately after usage. This value is in milliseconds.\n\t */\n\tcloseDbAfterMs?: number;\n}\n\n/**\n * A cache that can be used by the Fluid ODSP driver to cache data for faster performance\n */\nexport class FluidCache implements IPersistedCache {\n\tprivate readonly logger: ITelemetryLoggerExt;\n\n\tprivate readonly partitionKey: string | null;\n\n\tprivate readonly maxCacheItemAge: number;\n\tprivate readonly closeDbImmediately: boolean = true;\n\tprivate readonly closeDbAfterMs: number;\n\tprivate db: IDBPDatabase<FluidCacheDBSchema> | undefined;\n\tprivate dbCloseTimer: ReturnType<typeof setTimeout> | undefined;\n\tprivate dbReuseCount: number = -1;\n\n\tconstructor(config: FluidCacheConfig) {\n\t\tthis.logger = createChildLogger({ logger: config.logger });\n\t\tthis.partitionKey = config.partitionKey;\n\t\tthis.maxCacheItemAge = config.maxCacheItemAge;\n\t\tthis.closeDbAfterMs = config.closeDbAfterMs ?? 0;\n\t\tif (this.closeDbAfterMs > 0) {\n\t\t\tthis.closeDbImmediately = false;\n\t\t}\n\n\t\tscheduleIdleTask(async () => {\n\t\t\t// Log how much storage space is currently being used by indexed db.\n\t\t\t// NOTE: This API is not supported in all browsers and it doesn't let you see the size of a specific DB.\n\t\t\t// Exception added when eslint rule was added, this should be revisited when modifying this code\n\t\t\tif (navigator.storage?.estimate) {\n\t\t\t\tconst estimate = await navigator.storage.estimate();\n\n\t\t\t\t// Some browsers have a usageDetails property that will tell you\n\t\t\t\t// more detailed information on how the storage is being used\n\t\t\t\tlet indexedDBSize: number | undefined;\n\t\t\t\tif (\"usageDetails\" in estimate) {\n\t\t\t\t\tindexedDBSize = ((estimate as any).usageDetails as StorageQuotaUsageDetails)\n\t\t\t\t\t\t.indexedDB;\n\t\t\t\t}\n\n\t\t\t\tthis.logger.sendTelemetryEvent({\n\t\t\t\t\teventName: FluidCacheGenericEvent.FluidCacheStorageInfo,\n\t\t\t\t\tsubCategory: FluidCacheEventSubCategories.FluidCache,\n\t\t\t\t\tquota: estimate.quota,\n\t\t\t\t\tusage: estimate.usage,\n\t\t\t\t\tindexedDBSize,\n\t\t\t\t\tpkgVersion,\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\n\t\tscheduleIdleTask(async () => {\n\t\t\tlet db: IDBPDatabase<FluidCacheDBSchema> | undefined;\n\n\t\t\t// Delete entries that have not been accessed recently to clean up space\n\t\t\ttry {\n\t\t\t\tdb = await getFluidCacheIndexedDbInstance(this.logger);\n\n\t\t\t\tconst transaction = db.transaction(FluidDriverObjectStoreName, \"readwrite\");\n\t\t\t\tconst index = transaction.store.index(\"createdTimeMs\");\n\t\t\t\t// Get items which were cached before the maxCacheItemAge.\n\t\t\t\tconst keysToDelete = await index.getAllKeys(\n\t\t\t\t\tIDBKeyRange.upperBound(new Date().getTime() - this.maxCacheItemAge),\n\t\t\t\t);\n\n\t\t\t\tawait Promise.all(keysToDelete.map((key) => transaction.store.delete(key)));\n\t\t\t\tawait transaction.done;\n\t\t\t} catch (error: any) {\n\t\t\t\tthis.logger.sendErrorEvent(\n\t\t\t\t\t{\n\t\t\t\t\t\teventName: FluidCacheErrorEvent.FluidCacheDeleteOldEntriesError,\n\t\t\t\t\t\tpkgVersion,\n\t\t\t\t\t},\n\t\t\t\t\terror,\n\t\t\t\t);\n\t\t\t} finally {\n\t\t\t\tdb?.close();\n\t\t\t}\n\t\t});\n\t}\n\n\tprivate async openDb() {\n\t\tif (this.closeDbImmediately) {\n\t\t\treturn getFluidCacheIndexedDbInstance(this.logger);\n\t\t}\n\t\tif (this.db === undefined) {\n\t\t\tconst dbInstance = await getFluidCacheIndexedDbInstance(this.logger);\n\t\t\tif (this.db === undefined) {\n\t\t\t\t// Reset the counter on first open.\n\t\t\t\tthis.dbReuseCount = -1;\n\t\t\t\tthis.db = dbInstance;\n\t\t\t} else {\n\t\t\t\tdbInstance.close();\n\t\t\t\tthis.dbReuseCount += 1;\n\t\t\t\treturn this.db;\n\t\t\t}\n\t\t\t// Need to close the db on version change if opened.\n\t\t\tthis.db.onversionchange = (ev) => {\n\t\t\t\tthis.db?.close();\n\t\t\t\tthis.db = undefined;\n\t\t\t\tclearTimeout(this.dbCloseTimer);\n\t\t\t\tthis.dbCloseTimer = undefined;\n\t\t\t};\n\t\t\tthis.db.addEventListener(\"close\", (ev) => {\n\t\t\t\tclearTimeout(this.dbCloseTimer);\n\t\t\t\tthis.dbCloseTimer = undefined;\n\t\t\t\tthis.db = undefined;\n\t\t\t});\n\t\t\t// Schedule db close after this.closeDbAfterMs.\n\t\t\tassert(this.dbCloseTimer === undefined, 0x6c6 /* timer should not be set yet!! */);\n\t\t\tthis.dbCloseTimer = setTimeout(() => {\n\t\t\t\tthis.db?.close();\n\t\t\t\tthis.db = undefined;\n\t\t\t\tthis.dbCloseTimer = undefined;\n\t\t\t}, this.closeDbAfterMs);\n\t\t}\n\t\tassert(this.db !== undefined, 0x6c7 /* db should be intialized by now */);\n\t\tthis.dbReuseCount += 1;\n\t\treturn this.db;\n\t}\n\n\tprivate closeDb(db?: IDBPDatabase<FluidCacheDBSchema>) {\n\t\tif (this.closeDbImmediately) {\n\t\t\tdb?.close();\n\t\t}\n\t}\n\n\tpublic async removeEntries(file: IFileEntry): Promise<void> {\n\t\tlet db: IDBPDatabase<FluidCacheDBSchema> | undefined;\n\t\ttry {\n\t\t\tdb = await this.openDb();\n\n\t\t\tconst transaction = db.transaction(FluidDriverObjectStoreName, \"readwrite\");\n\t\t\tconst index = transaction.store.index(\"fileId\");\n\n\t\t\tconst keysToDelete = await index.getAllKeys(file.docId);\n\n\t\t\tawait Promise.all(keysToDelete.map((key) => transaction.store.delete(key)));\n\t\t\tawait transaction.done;\n\t\t} catch (error: any) {\n\t\t\tthis.logger.sendErrorEvent(\n\t\t\t\t{\n\t\t\t\t\teventName: FluidCacheErrorEvent.FluidCacheDeleteOldEntriesError,\n\t\t\t\t\tpkgVersion,\n\t\t\t\t},\n\t\t\t\terror,\n\t\t\t);\n\t\t} finally {\n\t\t\tthis.closeDb(db);\n\t\t}\n\t}\n\n\tpublic async get(cacheEntry: ICacheEntry): Promise<any> {\n\t\tconst startTime = performance.now();\n\n\t\tconst cachedItem = await this.getItemFromCache(cacheEntry);\n\n\t\tthis.logger.sendPerformanceEvent({\n\t\t\teventName: \"FluidCacheAccess\",\n\t\t\tcacheHit: cachedItem !== undefined,\n\t\t\ttype: cacheEntry.type,\n\t\t\tduration: performance.now() - startTime,\n\t\t\tdbOpenPerf: cachedItem?.dbOpenPerf,\n\t\t\tdbReuseCount: this.dbReuseCount,\n\t\t\tpkgVersion,\n\t\t});\n\n\t\t// Value will contain metadata like the expiry time, we just want to return the object we were asked to cache\n\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-return\n\t\treturn cachedItem?.cachedObject;\n\t}\n\n\tprivate async getItemFromCache(cacheEntry: ICacheEntry) {\n\t\tlet db: IDBPDatabase<FluidCacheDBSchema> | undefined;\n\t\ttry {\n\t\t\tconst key = getKeyForCacheEntry(cacheEntry);\n\n\t\t\tconst dbOpenStartTime = performance.now();\n\t\t\tdb = await this.openDb();\n\t\t\tconst dbOpenPerf = performance.now() - dbOpenStartTime;\n\t\t\tconst value = await db.get(FluidDriverObjectStoreName, key);\n\n\t\t\tif (!value) {\n\t\t\t\tthis.closeDb(db);\n\t\t\t\treturn undefined;\n\t\t\t}\n\n\t\t\t// If the data does not come from the same partition, don't return it\n\t\t\tif (value.partitionKey !== this.partitionKey) {\n\t\t\t\tthis.logger.sendTelemetryEvent({\n\t\t\t\t\teventName: FluidCacheGenericEvent.FluidCachePartitionKeyMismatch,\n\t\t\t\t\tsubCategory: FluidCacheEventSubCategories.FluidCache,\n\t\t\t\t\tpkgVersion,\n\t\t\t\t});\n\n\t\t\t\tthis.closeDb(db);\n\t\t\t\treturn undefined;\n\t\t\t}\n\n\t\t\tconst currentTime = new Date().getTime();\n\n\t\t\t// If too much time has passed since this cache entry was used, we will also return undefined\n\t\t\tif (currentTime - value.createdTimeMs > this.maxCacheItemAge) {\n\t\t\t\tthis.closeDb(db);\n\t\t\t\treturn undefined;\n\t\t\t}\n\n\t\t\tthis.closeDb(db);\n\t\t\treturn { ...value, dbOpenPerf };\n\t\t} catch (error: any) {\n\t\t\t// We can fail to open the db for a variety of reasons,\n\t\t\t// such as the database version having upgraded underneath us. Return undefined in this case\n\t\t\tthis.logger.sendErrorEvent(\n\t\t\t\t{ eventName: FluidCacheErrorEvent.FluidCacheGetError, pkgVersion },\n\t\t\t\terror,\n\t\t\t);\n\t\t\tthis.closeDb(db);\n\t\t\treturn undefined;\n\t\t}\n\t}\n\n\tpublic async put(entry: ICacheEntry, value: any): Promise<void> {\n\t\tlet db: IDBPDatabase<FluidCacheDBSchema> | undefined;\n\t\ttry {\n\t\t\tdb = await this.openDb();\n\n\t\t\tconst currentTime = new Date().getTime();\n\n\t\t\tawait db.put(\n\t\t\t\tFluidDriverObjectStoreName,\n\t\t\t\t{\n\t\t\t\t\tcachedObject: value,\n\t\t\t\t\tfileId: entry.file.docId,\n\t\t\t\t\ttype: entry.type,\n\t\t\t\t\tcacheItemId: entry.key,\n\t\t\t\t\tpartitionKey: this.partitionKey,\n\t\t\t\t\tcreatedTimeMs: currentTime,\n\t\t\t\t\tlastAccessTimeMs: currentTime,\n\t\t\t\t},\n\t\t\t\tgetKeyForCacheEntry(entry),\n\t\t\t);\n\t\t\tthis.closeDb(db);\n\t\t} catch (error: any) {\n\t\t\t// We can fail to open the db for a variety of reasons,\n\t\t\t// such as the database version having upgraded underneath us\n\t\t\tthis.logger.sendErrorEvent(\n\t\t\t\t{ eventName: FluidCacheErrorEvent.FluidCachePutError, pkgVersion },\n\t\t\t\terror,\n\t\t\t);\n\t\t} finally {\n\t\t\tthis.closeDb(db);\n\t\t}\n\t}\n}\n"]}
|
package/lib/packageVersion.d.ts
CHANGED
|
@@ -5,5 +5,5 @@
|
|
|
5
5
|
* THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY
|
|
6
6
|
*/
|
|
7
7
|
export declare const pkgName = "@fluidframework/driver-web-cache";
|
|
8
|
-
export declare const pkgVersion = "2.0.0-internal.
|
|
8
|
+
export declare const pkgVersion = "2.0.0-internal.6.0.1";
|
|
9
9
|
//# sourceMappingURL=packageVersion.d.ts.map
|
package/lib/packageVersion.js
CHANGED
|
@@ -5,5 +5,5 @@
|
|
|
5
5
|
* THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY
|
|
6
6
|
*/
|
|
7
7
|
export const pkgName = "@fluidframework/driver-web-cache";
|
|
8
|
-
export const pkgVersion = "2.0.0-internal.
|
|
8
|
+
export const pkgVersion = "2.0.0-internal.6.0.1";
|
|
9
9
|
//# sourceMappingURL=packageVersion.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,CAAC,MAAM,OAAO,GAAG,kCAAkC,CAAC;AAC1D,MAAM,CAAC,MAAM,UAAU,GAAG,sBAAsB,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n *\n * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY\n */\n\nexport const pkgName = \"@fluidframework/driver-web-cache\";\nexport const pkgVersion = \"2.0.0-internal.
|
|
1
|
+
{"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,CAAC,MAAM,OAAO,GAAG,kCAAkC,CAAC;AAC1D,MAAM,CAAC,MAAM,UAAU,GAAG,sBAAsB,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n *\n * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY\n */\n\nexport const pkgName = \"@fluidframework/driver-web-cache\";\nexport const pkgVersion = \"2.0.0-internal.6.0.1\";\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fluidframework/driver-web-cache",
|
|
3
|
-
"version": "2.0.0-internal.
|
|
3
|
+
"version": "2.0.0-internal.6.0.1",
|
|
4
4
|
"description": "Implementation of the driver caching API for a web browser",
|
|
5
5
|
"homepage": "https://fluidframework.com",
|
|
6
6
|
"repository": {
|
|
@@ -16,16 +16,16 @@
|
|
|
16
16
|
"types": "dist/index.d.ts",
|
|
17
17
|
"dependencies": {
|
|
18
18
|
"@fluidframework/common-utils": "^1.1.1",
|
|
19
|
-
"@fluidframework/core-interfaces": ">=2.0.0-internal.
|
|
20
|
-
"@fluidframework/odsp-driver-definitions": ">=2.0.0-internal.
|
|
21
|
-
"@fluidframework/telemetry-utils": ">=2.0.0-internal.
|
|
19
|
+
"@fluidframework/core-interfaces": ">=2.0.0-internal.6.0.1 <2.0.0-internal.6.1.0",
|
|
20
|
+
"@fluidframework/odsp-driver-definitions": ">=2.0.0-internal.6.0.1 <2.0.0-internal.6.1.0",
|
|
21
|
+
"@fluidframework/telemetry-utils": ">=2.0.0-internal.6.0.1 <2.0.0-internal.6.1.0",
|
|
22
22
|
"idb": "^6.1.2"
|
|
23
23
|
},
|
|
24
24
|
"devDependencies": {
|
|
25
25
|
"@fluid-tools/build-cli": "^0.21.0",
|
|
26
|
-
"@fluidframework/build-common": "^
|
|
26
|
+
"@fluidframework/build-common": "^2.0.0",
|
|
27
27
|
"@fluidframework/build-tools": "^0.21.0",
|
|
28
|
-
"@fluidframework/driver-web-cache-previous": "npm:@fluidframework/driver-web-cache@2.0.0-internal.
|
|
28
|
+
"@fluidframework/driver-web-cache-previous": "npm:@fluidframework/driver-web-cache@2.0.0-internal.6.0.0",
|
|
29
29
|
"@fluidframework/eslint-config-fluid": "^2.0.0",
|
|
30
30
|
"@microsoft/api-extractor": "^7.34.4",
|
|
31
31
|
"@types/jest": "22.2.3",
|
package/src/packageVersion.ts
CHANGED