import { FileMeta } from "../types.ts"; import type { SpacePrimitives } from "./space_primitives.ts"; /** * FallbackSpacePrimitives is a SpacePrimitives implementation that will try to fall back to another SpacePrimitives implementation for two * operations: * - readFile * - getFileMeta * The use case is primarily sync: when sync hasn't completed yet, we can fall back to HttpSpacePrimitives to fetch the file from the server. */ export class FallbackSpacePrimitives implements SpacePrimitives { constructor( private primary: SpacePrimitives, private fallback: SpacePrimitives, ) { } fetchFileList(): Promise { return this.primary.fetchFileList(); } async readFile(name: string): Promise<{ data: Uint8Array; meta: FileMeta }> { try { return await this.primary.readFile(name); } catch (e) { console.info( `Could not read file ${name} from primary, trying fallback, primary read error:`, e.message, ); try { const result = await this.fallback.readFile(name); return { data: result.data, meta: { ...result.meta, neverSync: true }, }; } catch (fallbackError: any) { console.error("Error during readFile fallback", fallbackError.message); // Fallback failed, so let's throw the original error throw e; } } } async getFileMeta(name: string): Promise { try { return await this.primary.getFileMeta(name); } catch (e) { console.info( `Could not fetch file ${name} metadata from primary, trying fallback, primary read error`, e.message, ); try { const meta = await this.fallback.getFileMeta(name); return { ...meta, neverSync: true }; } catch (fallbackError) { console.error( "Error during getFileMeta fallback", fallbackError.message, ); // Fallback failed, so let's throw the original error throw e; } } } writeFile( name: string, data: Uint8Array, selfUpdate?: boolean | undefined, meta?: FileMeta, ): Promise { return this.primary.writeFile(name, data, selfUpdate, meta); } deleteFile(name: string): Promise { return this.primary.deleteFile(name); } }