Skip to content

Commit

Permalink
retry on sqlite initialise (#469)
Browse files Browse the repository at this point in the history
  • Loading branch information
qiweiii authored Oct 26, 2023
1 parent dff1a43 commit daf66b0
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 27 deletions.
29 changes: 3 additions & 26 deletions packages/db/src/base-sql.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { BlockEntry, Database, KeyValueEntry, defaultLogger } from '@acala-network/chopsticks-core'
import { DataSource, QueryFailedError } from 'typeorm'
import { BlockEntry, Database, KeyValueEntry } from '@acala-network/chopsticks-core'
import { DataSource } from 'typeorm'
import { HexString } from '@polkadot/util/types'

import { BlockEntity, KeyValuePair } from './db/entities'

const logger = defaultLogger.child({ name: 'base-sql' })
import { retry } from './retry'

function Retryable<T>(
_target: any,
Expand All @@ -20,28 +19,6 @@ function Retryable<T>(
return descriptor
}

export async function retry<T>(fn: () => Promise<T>, maxRetries: number = 3, delay: number = 500): Promise<T> {
let retries = 0
while (retries < maxRetries) {
try {
return await fn()
} catch (error) {
if (error instanceof QueryFailedError) {
if (error.message.includes('SQLITE_BUSY')) {
retries++
logger.info(`SQLite is busy. Retrying in ${delay}ms (Attempt ${retries})...`)
await new Promise((r) => setTimeout(r, delay))
} else {
throw error
}
} else {
throw error
}
}
}
throw new Error(`Exceeded maximum retries (${maxRetries}) for SQLite busy error.`)
}

export abstract class BaseSqlDatabase implements Database {
abstract datasource: Promise<DataSource>

Expand Down
3 changes: 2 additions & 1 deletion packages/db/src/db/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { DataSource } from 'typeorm'

import * as entities from './entities'
import { retry } from '../retry'

export const openDb = async (dbPath: string): Promise<DataSource> => {
const source = new DataSource({
Expand All @@ -11,7 +12,7 @@ export const openDb = async (dbPath: string): Promise<DataSource> => {
logging: false,
})

await source.initialize()
await retry(() => source.initialize(), 3, 1000)

return source
}
26 changes: 26 additions & 0 deletions packages/db/src/retry.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { QueryFailedError } from 'typeorm'
import { defaultLogger } from '@acala-network/chopsticks-core'

export const logger = defaultLogger.child({ name: 'retry' })

export async function retry<T>(fn: () => Promise<T>, maxRetries: number = 3, delay: number = 500): Promise<T> {
let retries = 0
while (retries < maxRetries) {
try {
return await fn()
} catch (error) {
if (error instanceof QueryFailedError) {
if (error.message.includes('SQLITE_BUSY')) {
retries++
logger.info(`SQLite is busy. Retrying in ${delay}ms (Attempt ${retries})...`)
await new Promise((r) => setTimeout(r, delay))
} else {
throw error
}
} else {
throw error
}
}
}
throw new Error(`Exceeded maximum retries (${maxRetries}) for SQLite busy error.`)
}

0 comments on commit daf66b0

Please sign in to comment.