sliftutils 1.7.116 → 1.7.118

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.
@@ -43,6 +43,8 @@ export declare class SourceWrapper {
43
43
  seedLatency(ms: number): void;
44
44
  /** Median of the recent pings (API or URL-form, whichever this source measures), plus DISCONNECTED_LATENCY_PENALTY while the source is disconnected - so a down source still sorts and can still be picked, just after every connected one. Sources with no measurements yet sort last (Infinity), except our own in-process server, which is the best possible target (0). */
45
45
  getLatency(): number;
46
+ /** writeBlocked from missing backblaze credentials is re-checked on every write attempt: the secret load can fail TRANSIENTLY (early startup, a file-read hiccup), and one failed load must never permanently stop this process from writing to the bucket. The other writeBlocked reasons (read-only mode, browsers) are static properties of the process, so there is nothing to re-check. */
47
+ recheckWriteBlocked(): Promise<void>;
46
48
  /** Writes always go through the API, so a permission error throws to the caller on every write (and access granted in the meantime is picked up automatically). */
47
49
  write<T>(run: (archives: IArchives) => Promise<T>): Promise<T>;
48
50
  dispose(): void;
@@ -269,8 +269,21 @@ export class SourceWrapper {
269
269
  return median;
270
270
  }
271
271
 
272
+ /** writeBlocked from missing backblaze credentials is re-checked on every write attempt: the secret load can fail TRANSIENTLY (early startup, a file-read hiccup), and one failed load must never permanently stop this process from writing to the bucket. The other writeBlocked reasons (read-only mode, browsers) are static properties of the process, so there is nothing to re-check. */
273
+ public async recheckWriteBlocked(): Promise<void> {
274
+ if (!this.writeBlocked || this.api || this.disposed) return;
275
+ if (this.config.type !== "backblaze") return;
276
+ if (!await hasBackblazeCreds()) return;
277
+ this.api = new ArchivesBackblaze({ bucketName: parseBackblazeUrl(this.config.url).bucketName, public: this.config.public, immutable: this.config.immutable, allowedOrigins: this.config.allowedOrigins });
278
+ console.log(`Backblaze credentials are now available for ${this.getDebugName()}, unblocking writes (was blocked: ${this.writeBlocked})`);
279
+ this.writeBlocked = undefined;
280
+ }
281
+
272
282
  /** Writes always go through the API, so a permission error throws to the caller on every write (and access granted in the meantime is picked up automatically). */
273
283
  public async write<T>(run: (archives: IArchives) => Promise<T>): Promise<T> {
284
+ if (this.writeBlocked) {
285
+ await this.recheckWriteBlocked();
286
+ }
274
287
  if (this.writeBlocked) {
275
288
  throw new Error(`Writes are blocked on this source: ${this.writeBlocked}`);
276
289
  }
@@ -139,6 +139,7 @@ export declare const RemoteStorageController: import("socket-function/SocketFunc
139
139
  sourceConfig: SourceConfig;
140
140
  time: number;
141
141
  routes?: [number, number][];
142
+ internal?: boolean;
142
143
  }) => Promise<ArchiveFileInfo[]>;
143
144
  getArchivesConfig: (config: {
144
145
  account: string;
@@ -336,7 +336,7 @@ class RemoteStorageControllerBase {
336
336
  }
337
337
  @assertValidArgs
338
338
  @trackAccessCall("getChangesAfter")
339
- async getChangesAfter2(config: { account: string; bucketName: string; sourceConfig: SourceConfig; time: number; routes?: [number, number][] }): Promise<ArchiveFileInfo[]> {
339
+ async getChangesAfter2(config: { account: string; bucketName: string; sourceConfig: SourceConfig; time: number; routes?: [number, number][]; internal?: boolean }): Promise<ArchiveFileInfo[]> {
340
340
  return await withStore(config, store => store.getChangesAfter2(config));
341
341
  }
342
342
  @assertValidArgs
@@ -240,7 +240,7 @@ export class StoreSync {
240
240
  public async boundaryScanRemote(source: IArchives, config: { since: number; route?: [number, number] }): Promise<void> {
241
241
  let scanStart = Date.now();
242
242
  logSyncEvent({ event: "boundaryScanStart", store: this.store.folder, source: source.getDebugName(), since: config.since, route: config.route || FULL_ROUTE });
243
- let changes = await source.getChangesAfter2({ time: config.since, routes: config.route && [config.route] || undefined });
243
+ let changes = await source.getChangesAfter2({ time: config.since, routes: config.route && [config.route] || undefined, internal: true });
244
244
  let tally = newScanTally();
245
245
  for (let file of changes) {
246
246
  if (file.path === ROUTING_FILE) {
@@ -387,7 +387,7 @@ export class StoreSync {
387
387
  try {
388
388
  let attempts = 0;
389
389
  while (true) {
390
- files = await source.findInfo("");
390
+ files = await source.findInfo("", { internal: true });
391
391
  if (this.store.stopped.stop || state.stopped.stop) break;
392
392
  // What we believe the source has: whichever is larger of its previous listing and the index entries naming it as holder. Files do not just vanish - a listing far below this means the other end is briefly broken, and believing it would purge everything it held.
393
393
  let held = 0;
@@ -557,7 +557,7 @@ export class StoreSync {
557
557
  let { source, route } = this.store.sources[sourceIndex];
558
558
  let state = this.states[sourceIndex];
559
559
  let pollStart = Date.now();
560
- let changes = await source.getChangesAfter2({ time: state.changesAfterTime, routes: route && [route] || undefined });
560
+ let changes = await source.getChangesAfter2({ time: state.changesAfterTime, routes: route && [route] || undefined, internal: true });
561
561
  let tally = newScanTally();
562
562
  for (let file of changes) {
563
563
  tally[this.updateScanIndex(sourceIndex, file)]++;
package/yarn.lock CHANGED
@@ -1937,10 +1937,10 @@ slash@^3.0.0:
1937
1937
  resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634"
1938
1938
  integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==
1939
1939
 
1940
- socket-function@^1.2.32:
1941
- version "1.2.32"
1942
- resolved "https://registry.yarnpkg.com/socket-function/-/socket-function-1.2.32.tgz#9cd6ff3daf2e365bfaef5da0f35271f1c9fd89d3"
1943
- integrity sha512-d/nuXNXnikLG1eefi099+pG0Lqeibk7Pv92k01YXfTy3W1QjXCef0B9/0hrNJoSyB96r8mtSGk0JdKhCNMqGVQ==
1940
+ socket-function@^1.2.33:
1941
+ version "1.2.33"
1942
+ resolved "https://registry.yarnpkg.com/socket-function/-/socket-function-1.2.33.tgz#9137a8cc81f586e6650f837097e44202ec5e071e"
1943
+ integrity sha512-kdbwUDCtBnjqdfvH0JgmJZujP3IeuofSg5OsF2IcWCQ9YDiUisd5ydBzwBbjOLomErOnJgj6dySBp3dlTSzQIw==
1944
1944
  dependencies:
1945
1945
  "@types/pako" "^2.0.3"
1946
1946
  "@types/ws" "^8.5.3"