@fluidframework/routerlicious-driver 1.2.1 → 2.0.0-internal.1.0.0

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.
Files changed (76) hide show
  1. package/dist/deltaStorageService.d.ts +5 -3
  2. package/dist/deltaStorageService.d.ts.map +1 -1
  3. package/dist/deltaStorageService.js +9 -5
  4. package/dist/deltaStorageService.js.map +1 -1
  5. package/dist/documentService.d.ts +21 -5
  6. package/dist/documentService.d.ts.map +1 -1
  7. package/dist/documentService.js +92 -19
  8. package/dist/documentService.js.map +1 -1
  9. package/dist/documentServiceFactory.d.ts +3 -2
  10. package/dist/documentServiceFactory.d.ts.map +1 -1
  11. package/dist/documentServiceFactory.js +18 -23
  12. package/dist/documentServiceFactory.js.map +1 -1
  13. package/dist/documentStorageService.d.ts +1 -1
  14. package/dist/documentStorageService.d.ts.map +1 -1
  15. package/dist/documentStorageService.js +5 -5
  16. package/dist/documentStorageService.js.map +1 -1
  17. package/dist/packageVersion.d.ts +1 -1
  18. package/dist/packageVersion.d.ts.map +1 -1
  19. package/dist/packageVersion.js +1 -1
  20. package/dist/packageVersion.js.map +1 -1
  21. package/dist/restWrapper.js +2 -1
  22. package/dist/restWrapper.js.map +1 -1
  23. package/dist/shreddedSummaryDocumentStorageService.d.ts +3 -2
  24. package/dist/shreddedSummaryDocumentStorageService.d.ts.map +1 -1
  25. package/dist/shreddedSummaryDocumentStorageService.js +21 -7
  26. package/dist/shreddedSummaryDocumentStorageService.js.map +1 -1
  27. package/dist/tokens.d.ts +7 -0
  28. package/dist/tokens.d.ts.map +1 -1
  29. package/dist/tokens.js.map +1 -1
  30. package/dist/wholeSummaryDocumentStorageService.d.ts +4 -3
  31. package/dist/wholeSummaryDocumentStorageService.d.ts.map +1 -1
  32. package/dist/wholeSummaryDocumentStorageService.js +23 -10
  33. package/dist/wholeSummaryDocumentStorageService.js.map +1 -1
  34. package/lib/deltaStorageService.d.ts +5 -3
  35. package/lib/deltaStorageService.d.ts.map +1 -1
  36. package/lib/deltaStorageService.js +9 -5
  37. package/lib/deltaStorageService.js.map +1 -1
  38. package/lib/documentService.d.ts +21 -5
  39. package/lib/documentService.d.ts.map +1 -1
  40. package/lib/documentService.js +92 -19
  41. package/lib/documentService.js.map +1 -1
  42. package/lib/documentServiceFactory.d.ts +3 -2
  43. package/lib/documentServiceFactory.d.ts.map +1 -1
  44. package/lib/documentServiceFactory.js +18 -23
  45. package/lib/documentServiceFactory.js.map +1 -1
  46. package/lib/documentStorageService.d.ts +1 -1
  47. package/lib/documentStorageService.d.ts.map +1 -1
  48. package/lib/documentStorageService.js +5 -5
  49. package/lib/documentStorageService.js.map +1 -1
  50. package/lib/packageVersion.d.ts +1 -1
  51. package/lib/packageVersion.d.ts.map +1 -1
  52. package/lib/packageVersion.js +1 -1
  53. package/lib/packageVersion.js.map +1 -1
  54. package/lib/restWrapper.js +2 -1
  55. package/lib/restWrapper.js.map +1 -1
  56. package/lib/shreddedSummaryDocumentStorageService.d.ts +3 -2
  57. package/lib/shreddedSummaryDocumentStorageService.d.ts.map +1 -1
  58. package/lib/shreddedSummaryDocumentStorageService.js +21 -7
  59. package/lib/shreddedSummaryDocumentStorageService.js.map +1 -1
  60. package/lib/tokens.d.ts +7 -0
  61. package/lib/tokens.d.ts.map +1 -1
  62. package/lib/tokens.js.map +1 -1
  63. package/lib/wholeSummaryDocumentStorageService.d.ts +4 -3
  64. package/lib/wholeSummaryDocumentStorageService.d.ts.map +1 -1
  65. package/lib/wholeSummaryDocumentStorageService.js +23 -10
  66. package/lib/wholeSummaryDocumentStorageService.js.map +1 -1
  67. package/package.json +14 -14
  68. package/src/deltaStorageService.ts +10 -5
  69. package/src/documentService.ts +142 -42
  70. package/src/documentServiceFactory.ts +23 -25
  71. package/src/documentStorageService.ts +10 -3
  72. package/src/packageVersion.ts +1 -1
  73. package/src/restWrapper.ts +1 -1
  74. package/src/shreddedSummaryDocumentStorageService.ts +27 -13
  75. package/src/tokens.ts +7 -2
  76. package/src/wholeSummaryDocumentStorageService.ts +26 -12
@@ -17,11 +17,12 @@ export declare class WholeSummaryDocumentStorageService implements IDocumentStor
17
17
  private readonly driverPolicies?;
18
18
  private readonly blobCache;
19
19
  private readonly snapshotTreeCache;
20
- protected readonly noCacheGitManager?: GitManager | undefined;
21
- private readonly summaryUploadManager;
20
+ private readonly noCacheGitManager?;
21
+ private readonly getStorageManager;
22
22
  private firstVersionsCall;
23
23
  get repositoryUrl(): string;
24
- constructor(id: string, manager: GitManager, logger: ITelemetryLogger, policies?: IDocumentStorageServicePolicies, driverPolicies?: IRouterliciousDriverPolicies | undefined, blobCache?: ICache<ArrayBufferLike>, snapshotTreeCache?: ICache<ISnapshotTreeVersion>, noCacheGitManager?: GitManager | undefined);
24
+ private getSummaryUploadManager;
25
+ constructor(id: string, manager: GitManager, logger: ITelemetryLogger, policies?: IDocumentStorageServicePolicies, driverPolicies?: IRouterliciousDriverPolicies | undefined, blobCache?: ICache<ArrayBufferLike>, snapshotTreeCache?: ICache<ISnapshotTreeVersion>, noCacheGitManager?: GitManager | undefined, getStorageManager?: (disableCache?: boolean) => Promise<GitManager>);
25
26
  getVersions(versionId: string | null, count: number): Promise<IVersion[]>;
26
27
  getSnapshotTree(version?: IVersion): Promise<ISnapshotTree | null>;
27
28
  readBlob(blobId: string): Promise<ArrayBufferLike>;
@@ -1 +1 @@
1
- {"version":3,"file":"wholeSummaryDocumentStorageService.d.ts","sourceRoot":"","sources":["../src/wholeSummaryDocumentStorageService.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AAM3E,OAAO,EACH,uBAAuB,EACvB,eAAe,EACf,+BAA+B,EAClC,MAAM,oCAAoC,CAAC;AAI5C,OAAO,EACH,mBAAmB,EACnB,aAAa,EACb,cAAc,EACd,YAAY,EACZ,QAAQ,EACX,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EAEH,UAAU,EAGb,MAAM,wCAAwC,CAAC;AAEhD,OAAO,EAAE,MAAM,EAAiB,MAAM,SAAS,CAAC;AAChD,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,EAAE,4BAA4B,EAAE,MAAM,YAAY,CAAC;AAI1D,qBAAa,kCAAmC,YAAW,uBAAuB;IAS1E,SAAS,CAAC,QAAQ,CAAC,EAAE,EAAE,MAAM;IAC7B,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,UAAU;IACtC,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,gBAAgB;aAC3B,QAAQ,EAAE,+BAA+B;IACzD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC;IAChC,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAClC,SAAS,CAAC,QAAQ,CAAC,iBAAiB,CAAC;IAfzC,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAwB;IAC7D,OAAO,CAAC,iBAAiB,CAAiB;IAE1C,IAAW,aAAa,IAAI,MAAM,CAEjC;gBAGsB,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,UAAU,EACnB,MAAM,EAAE,gBAAgB,EAC3B,QAAQ,GAAE,+BAAoC,EAC7C,cAAc,CAAC,0CAA8B,EAC7C,SAAS,GAAE,MAAM,CAAC,eAAe,CAAuB,EACxD,iBAAiB,GAAE,MAAM,CAAC,oBAAoB,CAAuB,EACnE,iBAAiB,CAAC,wBAAY;IAIxC,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;IAuCzE,eAAe,CAAC,OAAO,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IAclE,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IA2BlD,wBAAwB,CAAC,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC;IAW1F,eAAe,CAAC,aAAa,EAAE,cAAc,GAAG,OAAO,CAAC,YAAY,CAAC;IAoBrE,UAAU,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,mBAAmB,CAAC;YAqB9D,yBAAyB;YAmDzB,aAAa;CAO9B"}
1
+ {"version":3,"file":"wholeSummaryDocumentStorageService.d.ts","sourceRoot":"","sources":["../src/wholeSummaryDocumentStorageService.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AAM3E,OAAO,EACH,uBAAuB,EACvB,eAAe,EACf,+BAA+B,EAClC,MAAM,oCAAoC,CAAC;AAI5C,OAAO,EACH,mBAAmB,EACnB,aAAa,EACb,cAAc,EACd,YAAY,EACZ,QAAQ,EACX,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EAEH,UAAU,EAGb,MAAM,wCAAwC,CAAC;AAEhD,OAAO,EAAE,MAAM,EAAiB,MAAM,SAAS,CAAC;AAChD,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,EAAE,4BAA4B,EAAE,MAAM,YAAY,CAAC;AAI1D,qBAAa,kCAAmC,YAAW,uBAAuB;IAa1E,SAAS,CAAC,QAAQ,CAAC,EAAE,EAAE,MAAM;IAC7B,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,UAAU;IACtC,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,gBAAgB;aAC3B,QAAQ,EAAE,+BAA+B;IACzD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC;IAChC,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAClC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAC;IACnC,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IApBtC,OAAO,CAAC,iBAAiB,CAAiB;IAE1C,IAAW,aAAa,IAAI,MAAM,CAEjC;YAEa,uBAAuB;gBAMd,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,UAAU,EACnB,MAAM,EAAE,gBAAgB,EAC3B,QAAQ,GAAE,+BAAoC,EAC7C,cAAc,CAAC,0CAA8B,EAC7C,SAAS,GAAE,MAAM,CAAC,eAAe,CAAuB,EACxD,iBAAiB,GAAE,MAAM,CAAC,oBAAoB,CAAuB,EACrE,iBAAiB,CAAC,wBAAY,EAC9B,iBAAiB,GAAE,CAAC,YAAY,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,UAAU,CACc;IAIvF,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;IA0CzE,eAAe,CAAC,OAAO,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IAclE,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IA4BlD,wBAAwB,CAAC,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC;IAc1F,eAAe,CAAC,aAAa,EAAE,cAAc,GAAG,OAAO,CAAC,YAAY,CAAC;IAqBrE,UAAU,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,mBAAmB,CAAC;YAsB9D,yBAAyB;YAkDzB,aAAa;CAO9B"}
@@ -9,7 +9,7 @@ import { PerformanceEvent } from "@fluidframework/telemetry-utils";
9
9
  import { InMemoryCache } from "./cache";
10
10
  const latestSnapshotId = "latest";
11
11
  export class WholeSummaryDocumentStorageService {
12
- constructor(id, manager, logger, policies = {}, driverPolicies, blobCache = new InMemoryCache(), snapshotTreeCache = new InMemoryCache(), noCacheGitManager) {
12
+ constructor(id, manager, logger, policies = {}, driverPolicies, blobCache = new InMemoryCache(), snapshotTreeCache = new InMemoryCache(), noCacheGitManager, getStorageManager = async (disableCache) => disableCache && this.noCacheGitManager !== undefined ? this.noCacheGitManager : this.manager) {
13
13
  this.id = id;
14
14
  this.manager = manager;
15
15
  this.logger = logger;
@@ -18,12 +18,16 @@ export class WholeSummaryDocumentStorageService {
18
18
  this.blobCache = blobCache;
19
19
  this.snapshotTreeCache = snapshotTreeCache;
20
20
  this.noCacheGitManager = noCacheGitManager;
21
+ this.getStorageManager = getStorageManager;
21
22
  this.firstVersionsCall = true;
22
- this.summaryUploadManager = new WholeSummaryUploadManager(manager);
23
23
  }
24
24
  get repositoryUrl() {
25
25
  return "";
26
26
  }
27
+ async getSummaryUploadManager() {
28
+ const manager = await this.getStorageManager();
29
+ return new WholeSummaryUploadManager(manager);
30
+ }
27
31
  async getVersions(versionId, count) {
28
32
  var _a;
29
33
  if (versionId !== this.id && versionId !== null) {
@@ -51,7 +55,10 @@ export class WholeSummaryDocumentStorageService {
51
55
  eventName: "getVersions",
52
56
  versionId: id,
53
57
  count,
54
- }, async () => this.manager.getCommits(id, count));
58
+ }, async () => {
59
+ const manager = await this.getStorageManager();
60
+ return manager.getCommits(id, count);
61
+ });
55
62
  return commits.map((commit) => ({
56
63
  date: commit.commit.author.date,
57
64
  id: commit.sha,
@@ -78,7 +85,8 @@ export class WholeSummaryDocumentStorageService {
78
85
  eventName: "readBlob",
79
86
  blobId,
80
87
  }, async (event) => {
81
- const response = await this.manager.getBlob(blobId);
88
+ const manager = await this.getStorageManager();
89
+ const response = await manager.getBlob(blobId);
82
90
  event.end({
83
91
  size: response.size,
84
92
  });
@@ -91,7 +99,11 @@ export class WholeSummaryDocumentStorageService {
91
99
  async uploadSummaryWithContext(summary, context) {
92
100
  const summaryHandle = await PerformanceEvent.timedExecAsync(this.logger, {
93
101
  eventName: "uploadSummaryWithContext",
94
- }, async () => { var _a; return this.summaryUploadManager.writeSummaryTree(summary, (_a = context.ackHandle) !== null && _a !== void 0 ? _a : "", "channel"); });
102
+ }, async () => {
103
+ var _a;
104
+ const summaryUploadManager = await this.getSummaryUploadManager();
105
+ return summaryUploadManager.writeSummaryTree(summary, (_a = context.ackHandle) !== null && _a !== void 0 ? _a : "", "channel");
106
+ });
95
107
  return summaryHandle;
96
108
  }
97
109
  async downloadSummary(summaryHandle) {
@@ -100,7 +112,8 @@ export class WholeSummaryDocumentStorageService {
100
112
  treeId: summaryHandle.handle,
101
113
  }, async (event) => {
102
114
  var _a;
103
- const response = await this.manager.getSummary(summaryHandle.handle);
115
+ const manager = await this.getStorageManager();
116
+ const response = await manager.getSummary(summaryHandle.handle);
104
117
  event.end({
105
118
  size: (_a = response.trees[0]) === null || _a === void 0 ? void 0 : _a.entries.length,
106
119
  });
@@ -115,7 +128,8 @@ export class WholeSummaryDocumentStorageService {
115
128
  eventName: "createBlob",
116
129
  size: uint8ArrayFile.length,
117
130
  }, async (event) => {
118
- const response = await this.manager.createBlob(Uint8ArrayToString(uint8ArrayFile, "base64"), "base64").then((r) => ({ id: r.sha, url: r.url }));
131
+ const manager = await this.getStorageManager();
132
+ const response = await manager.createBlob(Uint8ArrayToString(uint8ArrayFile, "base64"), "base64").then((r) => ({ id: r.sha, url: r.url }));
119
133
  event.end({
120
134
  blobId: response.id,
121
135
  });
@@ -132,9 +146,8 @@ export class WholeSummaryDocumentStorageService {
132
146
  treeId: versionId,
133
147
  }, async (event) => {
134
148
  var _a;
135
- const response = disableCache && this.noCacheGitManager !== undefined ?
136
- await this.noCacheGitManager.getSummary(versionId) :
137
- await this.manager.getSummary(versionId);
149
+ const manager = await this.getStorageManager(disableCache);
150
+ const response = await manager.getSummary(versionId);
138
151
  event.end({
139
152
  size: (_a = response.trees[0]) === null || _a === void 0 ? void 0 : _a.entries.length,
140
153
  });
@@ -1 +1 @@
1
- {"version":3,"file":"wholeSummaryDocumentStorageService.js","sourceRoot":"","sources":["../src/wholeSummaryDocumentStorageService.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 type { ITelemetryLogger } from \"@fluidframework/common-definitions\";\nimport {\n assert,\n stringToBuffer,\n Uint8ArrayToString,\n} from \"@fluidframework/common-utils\";\nimport {\n IDocumentStorageService,\n ISummaryContext,\n IDocumentStorageServicePolicies,\n} from \"@fluidframework/driver-definitions\";\nimport {\n convertSnapshotAndBlobsToSummaryTree,\n } from \"@fluidframework/driver-utils\";\nimport {\n ICreateBlobResponse,\n ISnapshotTree,\n ISummaryHandle,\n ISummaryTree,\n IVersion,\n} from \"@fluidframework/protocol-definitions\";\nimport {\n convertWholeFlatSummaryToSnapshotTreeAndBlobs,\n GitManager,\n ISummaryUploadManager,\n WholeSummaryUploadManager,\n} from \"@fluidframework/server-services-client\";\nimport { PerformanceEvent } from \"@fluidframework/telemetry-utils\";\nimport { ICache, InMemoryCache } from \"./cache\";\nimport { ISnapshotTreeVersion } from \"./definitions\";\nimport { IRouterliciousDriverPolicies } from \"./policies\";\n\nconst latestSnapshotId: string = \"latest\";\n\nexport class WholeSummaryDocumentStorageService implements IDocumentStorageService {\n private readonly summaryUploadManager: ISummaryUploadManager;\n private firstVersionsCall: boolean = true;\n\n public get repositoryUrl(): string {\n return \"\";\n }\n\n constructor(\n protected readonly id: string,\n protected readonly manager: GitManager,\n protected readonly logger: ITelemetryLogger,\n public readonly policies: IDocumentStorageServicePolicies = {},\n private readonly driverPolicies?: IRouterliciousDriverPolicies,\n private readonly blobCache: ICache<ArrayBufferLike> = new InMemoryCache(),\n private readonly snapshotTreeCache: ICache<ISnapshotTreeVersion> = new InMemoryCache(),\n protected readonly noCacheGitManager?: GitManager) {\n this.summaryUploadManager = new WholeSummaryUploadManager(manager);\n }\n\n public async getVersions(versionId: string | null, count: number): Promise<IVersion[]> {\n if (versionId !== this.id && versionId !== null) {\n // Blobs/Trees in this scenario will never have multiple versions, so return versionId as is\n return [{\n id: versionId,\n treeId: undefined!,\n }];\n }\n // If this is the first versions call for the document, we know we will want the latest summary.\n // Fetch latest summary, cache it, and return its id.\n if (this.firstVersionsCall && count === 1) {\n this.firstVersionsCall = false;\n const { id: _id, snapshotTree } = !this.driverPolicies?.enableDiscovery ?\n await this.fetchAndCacheSnapshotTree(latestSnapshotId, false) :\n await this.fetchAndCacheSnapshotTree(latestSnapshotId, true);\n return [{\n id: _id,\n treeId: snapshotTree.id!,\n }];\n }\n\n // Otherwise, get the latest version of the document as normal.\n const id = versionId ? versionId : this.id;\n const commits = await PerformanceEvent.timedExecAsync(\n this.logger,\n {\n eventName: \"getVersions\",\n versionId: id,\n count,\n },\n async () => this.manager.getCommits(id, count),\n );\n return commits.map((commit) => ({\n date: commit.commit.author.date,\n id: commit.sha,\n treeId: commit.commit.tree.sha,\n }));\n }\n\n public async getSnapshotTree(version?: IVersion): Promise<ISnapshotTree | null> {\n let requestVersion = version;\n if (!requestVersion) {\n const versions = await this.getVersions(this.id, 1);\n if (versions.length === 0) {\n return null;\n }\n\n requestVersion = versions[0];\n }\n\n return (await this.fetchAndCacheSnapshotTree(requestVersion.id)).snapshotTree;\n }\n\n public async readBlob(blobId: string): Promise<ArrayBufferLike> {\n const cachedBlob = await this.blobCache.get(blobId);\n if (cachedBlob !== undefined) {\n return cachedBlob;\n }\n\n const blob = await PerformanceEvent.timedExecAsync(\n this.logger,\n {\n eventName: \"readBlob\",\n blobId,\n },\n async (event) => {\n const response = await this.manager.getBlob(blobId);\n event.end({\n size: response.size,\n });\n return response;\n },\n );\n const bufferValue = stringToBuffer(blob.content, blob.encoding);\n\n await this.blobCache.put(blob.sha, bufferValue);\n\n return bufferValue;\n }\n\n public async uploadSummaryWithContext(summary: ISummaryTree, context: ISummaryContext): Promise<string> {\n const summaryHandle = await PerformanceEvent.timedExecAsync(\n this.logger,\n {\n eventName: \"uploadSummaryWithContext\",\n },\n async () => this.summaryUploadManager.writeSummaryTree(summary, context.ackHandle ?? \"\", \"channel\"),\n );\n return summaryHandle;\n }\n\n public async downloadSummary(summaryHandle: ISummaryHandle): Promise<ISummaryTree> {\n const wholeFlatSummary = await PerformanceEvent.timedExecAsync(\n this.logger,\n {\n eventName: \"getWholeFlatSummary\",\n treeId: summaryHandle.handle,\n },\n async (event) => {\n const response = await this.manager.getSummary(summaryHandle.handle);\n event.end({\n size: response.trees[0]?.entries.length,\n });\n return response;\n },\n );\n\n const { blobs, snapshotTree } = convertWholeFlatSummaryToSnapshotTreeAndBlobs(wholeFlatSummary, \"\");\n return convertSnapshotAndBlobsToSummaryTree(snapshotTree, blobs);\n }\n\n public async createBlob(file: ArrayBufferLike): Promise<ICreateBlobResponse> {\n const uint8ArrayFile = new Uint8Array(file);\n return PerformanceEvent.timedExecAsync(\n this.logger,\n {\n eventName: \"createBlob\",\n size: uint8ArrayFile.length,\n },\n async (event) => {\n const response = await this.manager.createBlob(\n Uint8ArrayToString(\n uint8ArrayFile, \"base64\"),\n \"base64\").then((r) => ({ id: r.sha, url: r.url }));\n event.end({\n blobId: response.id,\n });\n return response;\n },\n );\n }\n\n private async fetchAndCacheSnapshotTree(versionId: string, disableCache?: boolean): Promise<ISnapshotTreeVersion> {\n const cachedSnapshotTreeVersion = await this.snapshotTreeCache.get(versionId);\n if (cachedSnapshotTreeVersion !== undefined) {\n return { id: cachedSnapshotTreeVersion.id, snapshotTree: cachedSnapshotTreeVersion.snapshotTree };\n }\n\n const wholeFlatSummary = await PerformanceEvent.timedExecAsync(\n this.logger,\n {\n eventName: \"getWholeFlatSummary\",\n treeId: versionId,\n },\n async (event) => {\n const response = disableCache && this.noCacheGitManager !== undefined ?\n await this.noCacheGitManager.getSummary(versionId) :\n await this.manager.getSummary(versionId);\n event.end({\n size: response.trees[0]?.entries.length,\n });\n return response;\n },\n );\n const normalizedWholeSummary = convertWholeFlatSummaryToSnapshotTreeAndBlobs(wholeFlatSummary);\n const wholeFlatSummaryId: string = wholeFlatSummary.id;\n const snapshotTreeId = normalizedWholeSummary.snapshotTree.id;\n assert(snapshotTreeId !== undefined, 0x275 /* \"Root tree should contain the id\" */);\n const snapshotTreeVersion = { id: wholeFlatSummaryId, snapshotTree: normalizedWholeSummary.snapshotTree };\n\n const cachePs: Promise<any>[] = [\n this.snapshotTreeCache.put(\n snapshotTreeId,\n snapshotTreeVersion,\n ),\n this.initBlobCache(normalizedWholeSummary.blobs),\n ];\n if (snapshotTreeId !== versionId) {\n // versionId could be \"latest\". When summarizer checks cache for \"latest\", we want it to be available.\n // TODO: For in-memory cache, <latest,snapshotTree> will be a shared pointer with <snapshotId,snapshotTree>,\n // However, for something like Redis, this will cache the same value twice. Alternatively, could we simply\n // cache with versionId?\n cachePs.push(this.snapshotTreeCache.put(\n versionId,\n snapshotTreeVersion,\n ));\n }\n\n await Promise.all(cachePs);\n\n return snapshotTreeVersion;\n }\n\n private async initBlobCache(blobs: Map<string, ArrayBuffer>): Promise<void> {\n const blobCachePutPs: Promise<void>[] = [];\n blobs.forEach((value, id) => {\n blobCachePutPs.push(this.blobCache.put(id, value));\n });\n await Promise.all(blobCachePutPs);\n }\n}\n"]}
1
+ {"version":3,"file":"wholeSummaryDocumentStorageService.js","sourceRoot":"","sources":["../src/wholeSummaryDocumentStorageService.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 type { ITelemetryLogger } from \"@fluidframework/common-definitions\";\nimport {\n assert,\n stringToBuffer,\n Uint8ArrayToString,\n} from \"@fluidframework/common-utils\";\nimport {\n IDocumentStorageService,\n ISummaryContext,\n IDocumentStorageServicePolicies,\n} from \"@fluidframework/driver-definitions\";\nimport {\n convertSnapshotAndBlobsToSummaryTree,\n} from \"@fluidframework/driver-utils\";\nimport {\n ICreateBlobResponse,\n ISnapshotTree,\n ISummaryHandle,\n ISummaryTree,\n IVersion,\n} from \"@fluidframework/protocol-definitions\";\nimport {\n convertWholeFlatSummaryToSnapshotTreeAndBlobs,\n GitManager,\n ISummaryUploadManager,\n WholeSummaryUploadManager,\n} from \"@fluidframework/server-services-client\";\nimport { PerformanceEvent } from \"@fluidframework/telemetry-utils\";\nimport { ICache, InMemoryCache } from \"./cache\";\nimport { ISnapshotTreeVersion } from \"./definitions\";\nimport { IRouterliciousDriverPolicies } from \"./policies\";\n\nconst latestSnapshotId: string = \"latest\";\n\nexport class WholeSummaryDocumentStorageService implements IDocumentStorageService {\n private firstVersionsCall: boolean = true;\n\n public get repositoryUrl(): string {\n return \"\";\n }\n\n private async getSummaryUploadManager(): Promise<ISummaryUploadManager> {\n const manager = await this.getStorageManager();\n return new WholeSummaryUploadManager(manager);\n }\n\n constructor(\n protected readonly id: string,\n protected readonly manager: GitManager,\n protected readonly logger: ITelemetryLogger,\n public readonly policies: IDocumentStorageServicePolicies = {},\n private readonly driverPolicies?: IRouterliciousDriverPolicies,\n private readonly blobCache: ICache<ArrayBufferLike> = new InMemoryCache(),\n private readonly snapshotTreeCache: ICache<ISnapshotTreeVersion> = new InMemoryCache(),\n private readonly noCacheGitManager?: GitManager,\n private readonly getStorageManager: (disableCache?: boolean) => Promise<GitManager> = async (disableCache) =>\n disableCache && this.noCacheGitManager !== undefined ? this.noCacheGitManager : this.manager,\n ) {\n }\n\n public async getVersions(versionId: string | null, count: number): Promise<IVersion[]> {\n if (versionId !== this.id && versionId !== null) {\n // Blobs/Trees in this scenario will never have multiple versions, so return versionId as is\n return [{\n id: versionId,\n treeId: undefined!,\n }];\n }\n // If this is the first versions call for the document, we know we will want the latest summary.\n // Fetch latest summary, cache it, and return its id.\n if (this.firstVersionsCall && count === 1) {\n this.firstVersionsCall = false;\n const { id: _id, snapshotTree } = !this.driverPolicies?.enableDiscovery ?\n await this.fetchAndCacheSnapshotTree(latestSnapshotId, false) :\n await this.fetchAndCacheSnapshotTree(latestSnapshotId, true);\n return [{\n id: _id,\n treeId: snapshotTree.id!,\n }];\n }\n\n // Otherwise, get the latest version of the document as normal.\n const id = versionId ? versionId : this.id;\n const commits = await PerformanceEvent.timedExecAsync(\n this.logger,\n {\n eventName: \"getVersions\",\n versionId: id,\n count,\n },\n async () => {\n const manager = await this.getStorageManager();\n return manager.getCommits(id, count);\n },\n );\n return commits.map((commit) => ({\n date: commit.commit.author.date,\n id: commit.sha,\n treeId: commit.commit.tree.sha,\n }));\n }\n\n public async getSnapshotTree(version?: IVersion): Promise<ISnapshotTree | null> {\n let requestVersion = version;\n if (!requestVersion) {\n const versions = await this.getVersions(this.id, 1);\n if (versions.length === 0) {\n return null;\n }\n\n requestVersion = versions[0];\n }\n\n return (await this.fetchAndCacheSnapshotTree(requestVersion.id)).snapshotTree;\n }\n\n public async readBlob(blobId: string): Promise<ArrayBufferLike> {\n const cachedBlob = await this.blobCache.get(blobId);\n if (cachedBlob !== undefined) {\n return cachedBlob;\n }\n\n const blob = await PerformanceEvent.timedExecAsync(\n this.logger,\n {\n eventName: \"readBlob\",\n blobId,\n },\n async (event) => {\n const manager = await this.getStorageManager();\n const response = await manager.getBlob(blobId);\n event.end({\n size: response.size,\n });\n return response;\n },\n );\n const bufferValue = stringToBuffer(blob.content, blob.encoding);\n\n await this.blobCache.put(blob.sha, bufferValue);\n\n return bufferValue;\n }\n\n public async uploadSummaryWithContext(summary: ISummaryTree, context: ISummaryContext): Promise<string> {\n const summaryHandle = await PerformanceEvent.timedExecAsync(\n this.logger,\n {\n eventName: \"uploadSummaryWithContext\",\n },\n async () => {\n const summaryUploadManager = await this.getSummaryUploadManager();\n return summaryUploadManager.writeSummaryTree(summary, context.ackHandle ?? \"\", \"channel\");\n },\n );\n return summaryHandle;\n }\n\n public async downloadSummary(summaryHandle: ISummaryHandle): Promise<ISummaryTree> {\n const wholeFlatSummary = await PerformanceEvent.timedExecAsync(\n this.logger,\n {\n eventName: \"getWholeFlatSummary\",\n treeId: summaryHandle.handle,\n },\n async (event) => {\n const manager = await this.getStorageManager();\n const response = await manager.getSummary(summaryHandle.handle);\n event.end({\n size: response.trees[0]?.entries.length,\n });\n return response;\n },\n );\n\n const { blobs, snapshotTree } = convertWholeFlatSummaryToSnapshotTreeAndBlobs(wholeFlatSummary, \"\");\n return convertSnapshotAndBlobsToSummaryTree(snapshotTree, blobs);\n }\n\n public async createBlob(file: ArrayBufferLike): Promise<ICreateBlobResponse> {\n const uint8ArrayFile = new Uint8Array(file);\n return PerformanceEvent.timedExecAsync(\n this.logger,\n {\n eventName: \"createBlob\",\n size: uint8ArrayFile.length,\n },\n async (event) => {\n const manager = await this.getStorageManager();\n const response = await manager.createBlob(\n Uint8ArrayToString(\n uint8ArrayFile, \"base64\"),\n \"base64\").then((r) => ({ id: r.sha, url: r.url }));\n event.end({\n blobId: response.id,\n });\n return response;\n },\n );\n }\n\n private async fetchAndCacheSnapshotTree(versionId: string, disableCache?: boolean): Promise<ISnapshotTreeVersion> {\n const cachedSnapshotTreeVersion = await this.snapshotTreeCache.get(versionId);\n if (cachedSnapshotTreeVersion !== undefined) {\n return { id: cachedSnapshotTreeVersion.id, snapshotTree: cachedSnapshotTreeVersion.snapshotTree };\n }\n\n const wholeFlatSummary = await PerformanceEvent.timedExecAsync(\n this.logger,\n {\n eventName: \"getWholeFlatSummary\",\n treeId: versionId,\n },\n async (event) => {\n const manager = await this.getStorageManager(disableCache);\n const response = await manager.getSummary(versionId);\n event.end({\n size: response.trees[0]?.entries.length,\n });\n return response;\n },\n );\n const normalizedWholeSummary = convertWholeFlatSummaryToSnapshotTreeAndBlobs(wholeFlatSummary);\n const wholeFlatSummaryId: string = wholeFlatSummary.id;\n const snapshotTreeId = normalizedWholeSummary.snapshotTree.id;\n assert(snapshotTreeId !== undefined, 0x275 /* \"Root tree should contain the id\" */);\n const snapshotTreeVersion = { id: wholeFlatSummaryId, snapshotTree: normalizedWholeSummary.snapshotTree };\n\n const cachePs: Promise<any>[] = [\n this.snapshotTreeCache.put(\n snapshotTreeId,\n snapshotTreeVersion,\n ),\n this.initBlobCache(normalizedWholeSummary.blobs),\n ];\n if (snapshotTreeId !== versionId) {\n // versionId could be \"latest\". When summarizer checks cache for \"latest\", we want it to be available.\n // TODO: For in-memory cache, <latest,snapshotTree> will be a shared pointer with <snapshotId,snapshotTree>,\n // However, for something like Redis, this will cache the same value twice. Alternatively, could we simply\n // cache with versionId?\n cachePs.push(this.snapshotTreeCache.put(\n versionId,\n snapshotTreeVersion,\n ));\n }\n\n await Promise.all(cachePs);\n\n return snapshotTreeVersion;\n }\n\n private async initBlobCache(blobs: Map<string, ArrayBuffer>): Promise<void> {\n const blobCachePutPs: Promise<void>[] = [];\n blobs.forEach((value, id) => {\n blobCachePutPs.push(this.blobCache.put(id, value));\n });\n await Promise.all(blobCachePutPs);\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluidframework/routerlicious-driver",
3
- "version": "1.2.1",
3
+ "version": "2.0.0-internal.1.0.0",
4
4
  "description": "Socket.IO + Git implementation of Fluid service API",
5
5
  "homepage": "https://fluidframework.com",
6
6
  "repository": {
@@ -61,15 +61,15 @@
61
61
  },
62
62
  "dependencies": {
63
63
  "@fluidframework/common-definitions": "^0.20.1",
64
- "@fluidframework/common-utils": "^0.32.1",
65
- "@fluidframework/driver-base": "^1.2.1",
66
- "@fluidframework/driver-definitions": "^1.2.1",
67
- "@fluidframework/driver-utils": "^1.2.1",
68
- "@fluidframework/gitresources": "^0.1036.5000",
69
- "@fluidframework/protocol-base": "^0.1036.5000",
70
- "@fluidframework/protocol-definitions": "^0.1028.2000",
71
- "@fluidframework/server-services-client": "^0.1036.5000",
72
- "@fluidframework/telemetry-utils": "^1.2.1",
64
+ "@fluidframework/common-utils": "^1.0.0",
65
+ "@fluidframework/driver-base": "^2.0.0-internal.1.0.0",
66
+ "@fluidframework/driver-definitions": "^2.0.0-internal.1.0.0",
67
+ "@fluidframework/driver-utils": "^2.0.0-internal.1.0.0",
68
+ "@fluidframework/gitresources": "^0.1037.1000",
69
+ "@fluidframework/protocol-base": "^0.1037.1000",
70
+ "@fluidframework/protocol-definitions": "^1.0.0",
71
+ "@fluidframework/server-services-client": "^0.1037.1000",
72
+ "@fluidframework/telemetry-utils": "^2.0.0-internal.1.0.0",
73
73
  "cross-fetch": "^3.1.5",
74
74
  "json-stringify-safe": "5.0.1",
75
75
  "querystring": "^0.2.0",
@@ -79,10 +79,10 @@
79
79
  },
80
80
  "devDependencies": {
81
81
  "@fluidframework/build-common": "^0.24.0",
82
- "@fluidframework/build-tools": "^0.2.74327",
82
+ "@fluidframework/build-tools": "^0.3.1000",
83
83
  "@fluidframework/eslint-config-fluid": "^0.28.2000",
84
- "@fluidframework/mocha-test-setup": "^1.2.1",
85
- "@fluidframework/routerlicious-driver-previous": "npm:@fluidframework/routerlicious-driver@1.2.0",
84
+ "@fluidframework/mocha-test-setup": "^2.0.0-internal.1.0.0",
85
+ "@fluidframework/routerlicious-driver-previous": "npm:@fluidframework/routerlicious-driver@^1.0.0",
86
86
  "@microsoft/api-extractor": "^7.22.2",
87
87
  "@rushstack/eslint-config": "^2.5.1",
88
88
  "@types/mocha": "^9.1.1",
@@ -102,7 +102,7 @@
102
102
  "typescript-formatter": "7.1.0"
103
103
  },
104
104
  "typeValidation": {
105
- "version": "1.2.1",
105
+ "version": "2.0.0",
106
106
  "broken": {}
107
107
  }
108
108
  }
@@ -26,7 +26,7 @@ export class DocumentDeltaStorageService implements IDocumentDeltaStorageService
26
26
  constructor(
27
27
  private readonly tenantId: string,
28
28
  private readonly id: string,
29
- private readonly storageService: IDeltaStorageService,
29
+ private readonly deltaStorageService: IDeltaStorageService,
30
30
  private readonly documentStorageService: DocumentStorageService) {
31
31
  }
32
32
 
@@ -70,7 +70,7 @@ export class DocumentDeltaStorageService implements IDocumentDeltaStorageService
70
70
  }
71
71
  }
72
72
 
73
- return this.storageService.get(this.tenantId, this.id, from, to);
73
+ return this.deltaStorageService.get(this.tenantId, this.id, from, to);
74
74
  }
75
75
  }
76
76
 
@@ -81,7 +81,10 @@ export class DeltaStorageService implements IDeltaStorageService {
81
81
  constructor(
82
82
  private readonly url: string,
83
83
  private readonly restWrapper: RestWrapper,
84
- private readonly logger: ITelemetryLogger) {
84
+ private readonly logger: ITelemetryLogger,
85
+ private readonly getRestWrapper: () => Promise<RestWrapper> = async () => this.restWrapper,
86
+ private readonly getDeltaStorageUrl: () => string = () => this.url,
87
+ ) {
85
88
  }
86
89
 
87
90
  public async get(
@@ -98,8 +101,10 @@ export class DeltaStorageService implements IDeltaStorageService {
98
101
  to,
99
102
  },
100
103
  async (event) => {
101
- const response = await this.restWrapper.get<ISequencedDocumentMessage[]>(
102
- this.url,
104
+ const restWrapper = await this.getRestWrapper();
105
+ const url = this.getDeltaStorageUrl();
106
+ const response = await restWrapper.get<ISequencedDocumentMessage[]>(
107
+ url,
103
108
  { from: from - 1, to });
104
109
  event.end({
105
110
  count: response.length,
@@ -7,8 +7,9 @@ import { assert } from "@fluidframework/common-utils";
7
7
  import * as api from "@fluidframework/driver-definitions";
8
8
  import { RateLimiter } from "@fluidframework/driver-utils";
9
9
  import { IClient } from "@fluidframework/protocol-definitions";
10
- import { GitManager, Historian } from "@fluidframework/server-services-client";
10
+ import { GitManager, Historian, RestWrapper } from "@fluidframework/server-services-client";
11
11
  import io from "socket.io-client";
12
+ import { PerformanceEvent } from "@fluidframework/telemetry-utils";
12
13
  import { ITelemetryLogger } from "@fluidframework/common-definitions";
13
14
  import { DeltaStorageService, DocumentDeltaStorageService } from "./deltaStorageService";
14
15
  import { DocumentStorageService } from "./documentStorageService";
@@ -20,16 +21,35 @@ import { IRouterliciousDriverPolicies } from "./policies";
20
21
  import { ICache } from "./cache";
21
22
  import { ISnapshotTreeVersion } from "./definitions";
22
23
 
24
+ /**
25
+ * Amount of time between discoveries within which we don't need to rediscover on re-connect.
26
+ * Currently, R11s defines session length at 10 minutes. To avoid any weird unknown edge-cases though,
27
+ * we set the limit to 5 minutes here.
28
+ * In the future, we likely want to retrieve this information from service's "inactive session" definition.
29
+ */
30
+ const RediscoverAfterTimeSinceDiscoveryMs = 5 * 60000; // 5 minute
31
+
23
32
  /**
24
33
  * The DocumentService manages the Socket.IO connection and manages routing requests to connected
25
- * clients
34
+ * clients.
26
35
  */
27
36
  export class DocumentService implements api.IDocumentService {
37
+ private lastDiscoveredAt: number = Date.now();
38
+ private discoverP: Promise<void> | undefined;
39
+
40
+ private storageManager: GitManager | undefined;
41
+ private noCacheStorageManager: GitManager | undefined;
42
+ private ordererRestWrapper: RestWrapper | undefined;
43
+
44
+ public get resolvedUrl() {
45
+ return this._resolvedUrl;
46
+ }
47
+
28
48
  constructor(
29
- public readonly resolvedUrl: api.IResolvedUrl,
49
+ private _resolvedUrl: api.IResolvedUrl,
30
50
  protected ordererUrl: string,
31
- private readonly deltaStorageUrl: string,
32
- private readonly gitUrl: string,
51
+ private deltaStorageUrl: string,
52
+ private storageUrl: string,
33
53
  private readonly logger: ITelemetryLogger,
34
54
  protected tokenProvider: ITokenProvider,
35
55
  protected tenantId: string,
@@ -37,6 +57,7 @@ export class DocumentService implements api.IDocumentService {
37
57
  private readonly driverPolicies: IRouterliciousDriverPolicies,
38
58
  private readonly blobCache: ICache<ArrayBufferLike>,
39
59
  private readonly snapshotTreeCache: ICache<ISnapshotTreeVersion>,
60
+ private readonly discoverFluidResolvedUrl: () => Promise<api.IFluidResolvedUrl>,
40
61
  ) {
41
62
  }
42
63
 
@@ -54,32 +75,45 @@ export class DocumentService implements api.IDocumentService {
54
75
  return this.documentStorageService;
55
76
  }
56
77
 
57
- if (this.gitUrl === undefined) {
78
+ if (this.storageUrl === undefined) {
58
79
  return new NullBlobStorageService();
59
80
  }
60
81
 
61
- const rateLimiter = new RateLimiter(this.driverPolicies.maxConcurrentStorageRequests);
62
- const storageRestWrapper = await RouterliciousStorageRestWrapper.load(
63
- this.tenantId,
64
- this.documentId,
65
- this.tokenProvider,
66
- this.logger,
67
- rateLimiter,
68
- this.driverPolicies.enableRestLess,
69
- this.gitUrl,
70
- );
71
- const historian = new Historian(
72
- this.gitUrl,
73
- true,
74
- false,
75
- storageRestWrapper);
76
- const gitManager = new GitManager(historian);
77
- const noCacheHistorian = new Historian(
78
- this.gitUrl,
79
- true,
80
- true,
81
- storageRestWrapper);
82
- const noCacheGitManager = new GitManager(noCacheHistorian);
82
+ const getStorageManager = async (disableCache?: boolean): Promise<GitManager> => {
83
+ const shouldUpdateDiscoveredSessionInfo = this.shouldUpdateDiscoveredSessionInfo();
84
+ if (shouldUpdateDiscoveredSessionInfo) {
85
+ await this.refreshDiscovery();
86
+ }
87
+ if (!this.storageManager || !this.noCacheStorageManager || shouldUpdateDiscoveredSessionInfo) {
88
+ const rateLimiter = new RateLimiter(this.driverPolicies.maxConcurrentStorageRequests);
89
+ const storageRestWrapper = await RouterliciousStorageRestWrapper.load(
90
+ this.tenantId,
91
+ this.documentId,
92
+ this.tokenProvider,
93
+ this.logger,
94
+ rateLimiter,
95
+ this.driverPolicies.enableRestLess,
96
+ this.storageUrl,
97
+ );
98
+ const historian = new Historian(
99
+ this.storageUrl,
100
+ true,
101
+ false,
102
+ storageRestWrapper);
103
+ this.storageManager = new GitManager(historian);
104
+ const noCacheHistorian = new Historian(
105
+ this.storageUrl,
106
+ true,
107
+ true,
108
+ storageRestWrapper);
109
+ this.noCacheStorageManager = new GitManager(noCacheHistorian);
110
+ }
111
+
112
+ return disableCache ? this.noCacheStorageManager : this.storageManager;
113
+ };
114
+ // Initialize storageManager and noCacheStorageManager
115
+ const storageManager = await getStorageManager();
116
+ const noCacheStorageManager = await getStorageManager(true);
83
117
  const documentStorageServicePolicies: api.IDocumentStorageServicePolicies = {
84
118
  caching: this.driverPolicies.enablePrefetch
85
119
  ? api.LoaderCachingPolicy.Prefetch
@@ -89,13 +123,14 @@ export class DocumentService implements api.IDocumentService {
89
123
 
90
124
  this.documentStorageService = new DocumentStorageService(
91
125
  this.documentId,
92
- gitManager,
126
+ storageManager,
93
127
  this.logger,
94
128
  documentStorageServicePolicies,
95
129
  this.driverPolicies,
96
130
  this.blobCache,
97
131
  this.snapshotTreeCache,
98
- noCacheGitManager);
132
+ noCacheStorageManager,
133
+ getStorageManager);
99
134
  return this.documentStorageService;
100
135
  }
101
136
 
@@ -108,18 +143,38 @@ export class DocumentService implements api.IDocumentService {
108
143
  await this.connectToStorage();
109
144
  assert(!!this.documentStorageService, 0x0b1 /* "Storage service not initialized" */);
110
145
 
111
- const rateLimiter = new RateLimiter(this.driverPolicies.maxConcurrentOrdererRequests);
112
- const ordererRestWrapper = await RouterliciousOrdererRestWrapper.load(
146
+ const getRestWrapper = async (): Promise<RestWrapper> => {
147
+ const shouldUpdateDiscoveredSessionInfo = this.shouldUpdateDiscoveredSessionInfo();
148
+ if (shouldUpdateDiscoveredSessionInfo) {
149
+ await this.refreshDiscovery();
150
+ }
151
+ if (!this.ordererRestWrapper || shouldUpdateDiscoveredSessionInfo) {
152
+ const rateLimiter = new RateLimiter(this.driverPolicies.maxConcurrentOrdererRequests);
153
+ this.ordererRestWrapper = await RouterliciousOrdererRestWrapper.load(
154
+ this.tenantId,
155
+ this.documentId,
156
+ this.tokenProvider,
157
+ this.logger,
158
+ rateLimiter,
159
+ this.driverPolicies.enableRestLess,
160
+ );
161
+ }
162
+ return this.ordererRestWrapper;
163
+ };
164
+ const restWrapper = await getRestWrapper();
165
+ const deltaStorageService = new DeltaStorageService(
166
+ this.deltaStorageUrl,
167
+ restWrapper,
168
+ this.logger,
169
+ getRestWrapper,
170
+ () => this.deltaStorageUrl,
171
+ );
172
+ return new DocumentDeltaStorageService(
113
173
  this.tenantId,
114
174
  this.documentId,
115
- this.tokenProvider,
116
- this.logger,
117
- rateLimiter,
118
- this.driverPolicies.enableRestLess,
175
+ deltaStorageService,
176
+ this.documentStorageService,
119
177
  );
120
- const deltaStorage = new DeltaStorageService(this.deltaStorageUrl, ordererRestWrapper, this.logger);
121
- return new DocumentDeltaStorageService(this.tenantId, this.documentId,
122
- deltaStorage, this.documentStorageService);
123
178
  }
124
179
 
125
180
  /**
@@ -129,6 +184,9 @@ export class DocumentService implements api.IDocumentService {
129
184
  */
130
185
  public async connectToDeltaStream(client: IClient): Promise<api.IDocumentDeltaConnection> {
131
186
  const connect = async (refreshToken?: boolean) => {
187
+ if (this.shouldUpdateDiscoveredSessionInfo()) {
188
+ await this.refreshDiscovery();
189
+ }
132
190
  const ordererToken = await this.tokenProvider.fetchOrdererToken(
133
191
  this.tenantId,
134
192
  this.documentId,
@@ -147,16 +205,58 @@ export class DocumentService implements api.IDocumentService {
147
205
 
148
206
  // Attempt to establish connection.
149
207
  // Retry with new token on authorization error; otherwise, allow container layer to handle.
208
+ let connection: api.IDocumentDeltaConnection;
150
209
  try {
151
- const connection = await connect();
152
- return connection;
210
+ connection = await connect();
153
211
  } catch (error: any) {
154
212
  if (error?.statusCode === 401) {
155
213
  // Fetch new token and retry once,
156
214
  // otherwise 401 will be bubbled up as non-retriable AuthorizationError.
157
- return connect(true /* refreshToken */);
215
+ connection = await connect(true /* refreshToken */);
158
216
  }
159
217
  throw error;
160
218
  }
219
+ return connection;
220
+ }
221
+
222
+ /**
223
+ * Re-discover session URLs if necessary.
224
+ */
225
+ private async refreshDiscovery(): Promise<void> {
226
+ if (!this.discoverP) {
227
+ this.discoverP = PerformanceEvent.timedExecAsync(
228
+ this.logger,
229
+ {
230
+ eventName: "refreshSessionDiscovery",
231
+ },
232
+ async () => this.refreshDiscoveryCore(),
233
+ );
234
+ }
235
+ return this.discoverP;
236
+ }
237
+
238
+ private async refreshDiscoveryCore(): Promise<void> {
239
+ const fluidResolvedUrl = await this.discoverFluidResolvedUrl();
240
+ this._resolvedUrl = fluidResolvedUrl;
241
+ this.storageUrl = fluidResolvedUrl.endpoints.storageUrl;
242
+ this.ordererUrl = fluidResolvedUrl.endpoints.ordererUrl;
243
+ this.deltaStorageUrl = fluidResolvedUrl.endpoints.deltaStorageUrl;
244
+ this.lastDiscoveredAt = Date.now();
245
+ }
246
+
247
+ /**
248
+ * Whether enough time has passed since last disconnect to warrant a new discovery call on reconnect.
249
+ */
250
+ private shouldUpdateDiscoveredSessionInfo(): boolean {
251
+ if (!this.driverPolicies.enableDiscovery) {
252
+ return false;
253
+ }
254
+ const now = Date.now();
255
+ // When connection is disconnected, we cannot know if session has moved or document has been deleted
256
+ // without re-doing discovery on the next attempt to connect.
257
+ // Disconnect event is not so reliable in local testing. To ensure re-discovery when necessary,
258
+ // re-discover if enough time has passed since last discovery.
259
+ const pastLastDiscoveryTimeThreshold = (now - this.lastDiscoveredAt) > RediscoverAfterTimeSinceDiscoveryMs;
260
+ return pastLastDiscoveryTimeThreshold;
161
261
  }
162
262
  }