sliftutils 1.7.40 → 1.7.42
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/index.d.ts +2 -0
- package/misc/dist/environment.ts.cache +2 -2
- package/misc/dist/getSecret.ts.cache +2 -2
- package/misc/dist/strings.ts.cache +2 -2
- package/misc/dist/zip.ts.cache +2 -2
- package/misc/https/dist/certs.ts.cache +2 -2
- package/misc/https/dist/persistentLocalStorage.ts.cache +2 -2
- package/package.json +1 -1
- package/render-utils/dist/observer.tsx.cache +2 -2
- package/storage/BulkDatabase2/dist/BulkDatabaseBase.ts.cache +2 -2
- package/storage/BulkDatabase2/dist/BulkDatabaseFormat.ts.cache +2 -2
- package/storage/BulkDatabase2/dist/BulkDatabaseMerge.ts.cache +2 -2
- package/storage/BulkDatabase2/dist/BulkDatabaseReader.ts.cache +2 -2
- package/storage/BulkDatabase2/dist/LoadedIndex.ts.cache +2 -2
- package/storage/BulkDatabase2/dist/WriteOverlay.ts.cache +2 -2
- package/storage/BulkDatabase2/dist/blockCache.ts.cache +2 -2
- package/storage/BulkDatabase2/dist/mergeLock.ts.cache +2 -2
- package/storage/BulkDatabase2/dist/mergeMarkers.ts.cache +2 -2
- package/storage/BulkDatabase2/dist/streamLog.ts.cache +2 -2
- package/storage/BulkDatabase2/dist/syncClient.ts.cache +2 -2
- package/storage/dist/ArchivesDisk.ts.cache +2 -2
- package/storage/dist/FileFolderAPI.tsx.cache +2 -2
- package/storage/dist/IArchives.ts.cache +2 -2
- package/storage/dist/IndexedDBFileFolderAPI.ts.cache +2 -2
- package/storage/dist/JSONStorage.ts.cache +2 -2
- package/storage/dist/PendingManager.tsx.cache +2 -2
- package/storage/dist/TransactionStorage.ts.cache +2 -2
- package/storage/dist/backblaze.ts.cache +2 -2
- package/storage/dist/fileSystemPointer.ts.cache +2 -2
- package/storage/dist/remoteFileStorage.ts.cache +2 -2
- package/storage/remoteStorage/dist/ArchivesRemote.ts.cache +2 -2
- package/storage/remoteStorage/dist/ArchivesUrl.ts.cache +2 -2
- package/storage/remoteStorage/dist/blobStore.ts.cache +2 -2
- package/storage/remoteStorage/dist/cliArgs.ts.cache +2 -2
- package/storage/remoteStorage/dist/createArchives.ts.cache +2 -2
- package/storage/remoteStorage/dist/deployTakeover.ts.cache +2 -2
- package/storage/remoteStorage/dist/intermediateSources.ts.cache +2 -2
- package/storage/remoteStorage/dist/remoteConfig.ts.cache +2 -2
- package/storage/remoteStorage/dist/sourceWrapper.ts.cache +17 -4
- package/storage/remoteStorage/dist/storageClientController.ts.cache +2 -2
- package/storage/remoteStorage/dist/storageController.ts.cache +2 -2
- package/storage/remoteStorage/dist/storageServerState.ts.cache +9 -36
- package/storage/remoteStorage/sourceWrapper.d.ts +2 -0
- package/storage/remoteStorage/sourceWrapper.ts +14 -2
- package/storage/remoteStorage/storageServerState.ts +5 -31
|
@@ -21,6 +21,8 @@ export declare class SourceWrapper {
|
|
|
21
21
|
}): Promise<SourceWrapper>;
|
|
22
22
|
getDebugName(): string;
|
|
23
23
|
isConnected(): boolean;
|
|
24
|
+
/** A source whose window has passed is never read from or written to (see the window checks in ArchivesChain), and an intermediate only exists for the minutes of a deploy switchover - on either, being unreachable is expected, not a problem to report. */
|
|
25
|
+
private isConnectionProblemWorthReporting;
|
|
24
26
|
/** Call after a request failed while isConnected() was false: starts (if not already running) the background reconnect loop. Never blocks - the failed request still throws. */
|
|
25
27
|
noteFailure(): void;
|
|
26
28
|
private reconnectLoop;
|
|
@@ -101,11 +101,19 @@ export class SourceWrapper {
|
|
|
101
101
|
return this.remote.isConnected();
|
|
102
102
|
}
|
|
103
103
|
|
|
104
|
+
/** A source whose window has passed is never read from or written to (see the window checks in ArchivesChain), and an intermediate only exists for the minutes of a deploy switchover - on either, being unreachable is expected, not a problem to report. */
|
|
105
|
+
private isConnectionProblemWorthReporting(): boolean {
|
|
106
|
+
if (this.config.intermediate) return false;
|
|
107
|
+
return this.config.validWindow[1] > Date.now();
|
|
108
|
+
}
|
|
109
|
+
|
|
104
110
|
/** Call after a request failed while isConnected() was false: starts (if not already running) the background reconnect loop. Never blocks - the failed request still throws. */
|
|
105
111
|
public noteFailure(): void {
|
|
106
112
|
if (!this.background || this.disposed || this.reconnectRunning) return;
|
|
107
113
|
if (this.isConnected()) return;
|
|
108
|
-
|
|
114
|
+
if (this.isConnectionProblemWorthReporting()) {
|
|
115
|
+
console.error(`Cannot connect to storage ${this.getDebugName()}`);
|
|
116
|
+
}
|
|
109
117
|
this.reconnectRunning = true;
|
|
110
118
|
void this.reconnectLoop();
|
|
111
119
|
}
|
|
@@ -126,7 +134,9 @@ export class SourceWrapper {
|
|
|
126
134
|
} catch (e) {
|
|
127
135
|
// Even a failing call (e.g. access denied) proves the connection is back
|
|
128
136
|
if (this.isConnected()) break;
|
|
129
|
-
|
|
137
|
+
if (this.isConnectionProblemWorthReporting()) {
|
|
138
|
+
console.warn(`Cannot connect to storage ${this.getDebugName()}, retrying in ${Math.round(retryDelay / 1000)}s. ${(e as Error).stack ?? e}`);
|
|
139
|
+
}
|
|
130
140
|
}
|
|
131
141
|
retryDelay = Math.min(RETRY_MAX_DELAY, retryDelay * RETRY_GROWTH);
|
|
132
142
|
}
|
|
@@ -182,6 +192,8 @@ export class SourceWrapper {
|
|
|
182
192
|
public startPinging(): void {
|
|
183
193
|
const remote = this.remote;
|
|
184
194
|
if (!remote || this.pingTimer || this.disposed) return;
|
|
195
|
+
// Latency only decides which shard a variable-shard write materializes into, and a source whose window has passed never receives writes - so measuring it is pointless traffic
|
|
196
|
+
if (this.config.validWindow[1] <= Date.now()) return;
|
|
185
197
|
let measure = async () => {
|
|
186
198
|
let start = Date.now();
|
|
187
199
|
try {
|
|
@@ -756,40 +756,14 @@ async function propagateRoutingConfig(loaded: LoadedBucket, next: RemoteConfig,
|
|
|
756
756
|
}
|
|
757
757
|
}
|
|
758
758
|
|
|
759
|
-
/** Every bucket that exists on this server's disk, as account/bucketName keys. */
|
|
760
|
-
async function getAllBucketKeys(): Promise<string[]> {
|
|
761
|
-
let root = path.join(getStorageServerConfig().folder, "buckets2");
|
|
762
|
-
let accounts: string[];
|
|
763
|
-
try {
|
|
764
|
-
accounts = await fs.promises.readdir(root);
|
|
765
|
-
} catch {
|
|
766
|
-
return [];
|
|
767
|
-
}
|
|
768
|
-
let keys: string[] = [];
|
|
769
|
-
for (let account of accounts) {
|
|
770
|
-
let names: string[];
|
|
771
|
-
try {
|
|
772
|
-
names = await fs.promises.readdir(path.join(root, account));
|
|
773
|
-
} catch {
|
|
774
|
-
continue;
|
|
775
|
-
}
|
|
776
|
-
for (let bucketName of names) {
|
|
777
|
-
keys.push(`${account}/${bucketName}`);
|
|
778
|
-
}
|
|
779
|
-
}
|
|
780
|
-
return keys;
|
|
781
|
-
}
|
|
782
|
-
|
|
783
759
|
async function maintainIntermediates(): Promise<void> {
|
|
784
760
|
let { domain, port } = getStorageServerConfig();
|
|
785
761
|
let takeover = getTakeoverIntermediate();
|
|
786
|
-
//
|
|
787
|
-
for (let key of
|
|
788
|
-
let
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
return undefined;
|
|
792
|
-
});
|
|
762
|
+
// ONLY buckets already in memory. A switchover must never load a bucket: loading starts its synchronization, and buckets nothing has touched (legacy ones especially) have no writes to hand off in the first place. One that does get used mid-switchover loads on that access, and the next pass gives it its window.
|
|
763
|
+
for (let key of [...buckets.keys()]) {
|
|
764
|
+
let loadedPromise = buckets.get(key);
|
|
765
|
+
if (!loadedPromise) continue;
|
|
766
|
+
let loaded = await loadedPromise.catch(() => undefined);
|
|
793
767
|
if (!loaded) continue;
|
|
794
768
|
let expired = expireIntermediateSources(loaded.routing, Date.now());
|
|
795
769
|
if (JSON.stringify(expired) !== JSON.stringify(loaded.routing)) {
|