diff --git a/src/components/database/index.ts b/src/components/database/index.ts index 15deabbff..320743250 100644 --- a/src/components/database/index.ts +++ b/src/components/database/index.ts @@ -11,6 +11,7 @@ import { import { DATABASE_LOGGER } from '../../utils/logging/common.js' import { validateObject } from '../core/utils/validateDdoHandler.js' import { ENVIRONMENT_VARIABLES, TYPESENSE_HITS_CAP } from '../../utils/constants.js' +import { SQLiteProvider } from './sqlite.js' export class OrderDatabase { private provider: Typesense @@ -608,22 +609,32 @@ export class DdoDatabase { } export class NonceDatabase { - private provider: Typesense + private provider: Typesense | SQLiteProvider constructor( private config: OceanNodeDBConfig, private schema: Schema ) { return (async (): Promise => { - this.provider = new Typesense({ - ...convertTypesenseConfig(this.config.url), - logger: DATABASE_LOGGER - }) try { + this.provider = new Typesense({ + ...convertTypesenseConfig(this.config.url), + logger: DATABASE_LOGGER + }) await this.provider.collections(this.schema.name).retrieve() } catch (error) { if (error instanceof TypesenseError && error.httpStatus === 404) { - await this.provider.collections().create(this.schema) + await (this.provider as Typesense).collections().create(this.schema) + } else { + // Fall back to SQLite + DATABASE_LOGGER.logMessageWithEmoji( + 'Typesense not available, falling back to SQLite', + true, + GENERIC_EMOJIS.EMOJI_CROSS_MARK, + LOG_LEVELS_STR.LEVEL_WARN + ) + this.provider = new SQLiteProvider('nonceDatabase.sqlite') + await this.provider.createTable() } } return this @@ -632,10 +643,14 @@ export class NonceDatabase { async create(address: string, nonce: number) { try { - return await this.provider - .collections(this.schema.name) - .documents() - .create({ id: address, nonce }) + if (this.provider instanceof Typesense) { + return await this.provider + .collections(this.schema.name) + .documents() + .create({ id: address, nonce }) + } else { + return await this.provider.create(address, nonce) + } } catch (error) { const errorMsg = `Error when creating new nonce entry ${nonce} for address ${address}: ` + @@ -652,10 +667,14 @@ export class NonceDatabase { async retrieve(address: string) { try { - return await this.provider - .collections(this.schema.name) - .documents() - .retrieve(address) + if (this.provider instanceof Typesense) { + return await this.provider + .collections(this.schema.name) + .documents() + .retrieve(address) + } else { + return await this.provider.retrieve(address) + } } catch (error) { const errorMsg = `Error when retrieving nonce entry for address ${address}: ` + error.message @@ -671,12 +690,20 @@ export class NonceDatabase { async update(address: string, nonce: number) { try { - return await this.provider - .collections(this.schema.name) - .documents() - .update(address, { nonce }) + if (this.provider instanceof Typesense) { + return await this.provider + .collections(this.schema.name) + .documents() + .update(address, { nonce }) + } else { + return await this.provider.update(address, nonce) + } } catch (error) { - if (error instanceof TypesenseError && error.httpStatus === 404) { + if ( + this.provider instanceof Typesense && + error instanceof TypesenseError && + error.httpStatus === 404 + ) { return await this.provider .collections(this.schema.name) .documents() @@ -697,7 +724,14 @@ export class NonceDatabase { async delete(address: string) { try { - return await this.provider.collections(this.schema.name).documents().delete(address) + if (this.provider instanceof Typesense) { + return await this.provider + .collections(this.schema.name) + .documents() + .delete(address) + } else { + return await this.provider.delete(address) + } } catch (error) { const errorMsg = `Error when deleting nonce entry for address ${address}: ` + error.message diff --git a/src/components/database/sqlite.ts b/src/components/database/sqlite.ts index 339e9a27e..23d2e4d97 100644 --- a/src/components/database/sqlite.ts +++ b/src/components/database/sqlite.ts @@ -1,7 +1,14 @@ import { schemas, Schema } from './schemas.js' import sqlite3 from 'sqlite3' -export class SQLiteProvider { +interface DatabaseProvider { + create(address: string, nonce: number): Promise + retrieve(address: string): Promise + update(address: string, nonce: number): Promise + delete(address: string): Promise +} + +export class SQLiteProvider implements DatabaseProvider { private db: sqlite3.Database private schema: Schema