mirror of
https://codeberg.org/timelimit/timelimit-server.git
synced 2025-10-05 19:42:39 +02:00
Retry transactions
This commit is contained in:
parent
9b8caccfbd
commit
f5198c7c0b
2 changed files with 45 additions and 7 deletions
|
@ -42,6 +42,7 @@ import { createU2fKeyModel, U2fKeyModelStatic } from './u2fkey'
|
||||||
import { createUsedTimeModel, UsedTimeModelStatic } from './usedtime'
|
import { createUsedTimeModel, UsedTimeModelStatic } from './usedtime'
|
||||||
import { createUserModel, UserModelStatic } from './user'
|
import { createUserModel, UserModelStatic } from './user'
|
||||||
import { createUserLimitLoginCategoryModel, UserLimitLoginCategoryModelStatic } from './userlimitlogincategory'
|
import { createUserLimitLoginCategoryModel, UserLimitLoginCategoryModelStatic } from './userlimitlogincategory'
|
||||||
|
import { shouldRetryWithException } from './utils/serialized'
|
||||||
|
|
||||||
export type Transaction = Sequelize.Transaction
|
export type Transaction = Sequelize.Transaction
|
||||||
|
|
||||||
|
@ -71,10 +72,18 @@ export interface Database {
|
||||||
usedTime: UsedTimeModelStatic
|
usedTime: UsedTimeModelStatic
|
||||||
user: UserModelStatic
|
user: UserModelStatic
|
||||||
userLimitLoginCategory: UserLimitLoginCategoryModelStatic
|
userLimitLoginCategory: UserLimitLoginCategoryModelStatic
|
||||||
transaction: <T> (autoCallback: (t: Transaction) => Promise<T>, options?: { transaction: Transaction }) => Promise<T>
|
transaction: <T> (
|
||||||
|
autoCallback: (t: Transaction) => Promise<T>,
|
||||||
|
options?: TransactionOptions
|
||||||
|
) => Promise<T>
|
||||||
dialect: string
|
dialect: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface TransactionOptions {
|
||||||
|
transaction?: Transaction
|
||||||
|
disableRetry?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
const createDatabase = (sequelize: Sequelize.Sequelize): Database => ({
|
const createDatabase = (sequelize: Sequelize.Sequelize): Database => ({
|
||||||
addDeviceToken: createAddDeviceTokenModel(sequelize),
|
addDeviceToken: createAddDeviceTokenModel(sequelize),
|
||||||
authtoken: createAuthtokenModel(sequelize),
|
authtoken: createAuthtokenModel(sequelize),
|
||||||
|
@ -101,10 +110,39 @@ const createDatabase = (sequelize: Sequelize.Sequelize): Database => ({
|
||||||
usedTime: createUsedTimeModel(sequelize),
|
usedTime: createUsedTimeModel(sequelize),
|
||||||
user: createUserModel(sequelize),
|
user: createUserModel(sequelize),
|
||||||
userLimitLoginCategory: createUserLimitLoginCategoryModel(sequelize),
|
userLimitLoginCategory: createUserLimitLoginCategoryModel(sequelize),
|
||||||
transaction: <T> (autoCallback: (transaction: Transaction) => Promise<T>, options?: { transaction: Transaction }) => (sequelize.transaction({
|
async transaction<T>(
|
||||||
|
autoCallback: (transaction: Transaction) => Promise<T>,
|
||||||
|
options?: TransactionOptions
|
||||||
|
): Promise<T> {
|
||||||
|
const runAttempt = () => sequelize.transaction({
|
||||||
isolationLevel: Sequelize.Transaction.ISOLATION_LEVELS.SERIALIZABLE,
|
isolationLevel: Sequelize.Transaction.ISOLATION_LEVELS.SERIALIZABLE,
|
||||||
transaction: options?.transaction
|
transaction: options?.transaction
|
||||||
}, autoCallback)) as Promise<T>,
|
}, autoCallback)
|
||||||
|
|
||||||
|
const delay = (time: number) => new Promise((resolve) => setTimeout(resolve, time))
|
||||||
|
|
||||||
|
try {
|
||||||
|
return await runAttempt()
|
||||||
|
} catch (ex) {
|
||||||
|
if (
|
||||||
|
options?.disableRetry ||
|
||||||
|
options?.transaction ||
|
||||||
|
!shouldRetryWithException(this, ex)
|
||||||
|
) throw ex
|
||||||
|
}
|
||||||
|
|
||||||
|
await delay(10 * (1 + Math.random()))
|
||||||
|
|
||||||
|
try {
|
||||||
|
return await runAttempt()
|
||||||
|
} catch (ex) {
|
||||||
|
if (!shouldRetryWithException(this, ex)) throw ex
|
||||||
|
}
|
||||||
|
|
||||||
|
await delay(100 * (1 + Math.random()))
|
||||||
|
|
||||||
|
return await runAttempt()
|
||||||
|
},
|
||||||
dialect: sequelize.getDialect()
|
dialect: sequelize.getDialect()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -86,8 +86,8 @@ export async function assertSerializeableTransactionsAreWorking (database: Datab
|
||||||
await database.config.update({ value: 'd' }, { where: { id: configItemIds.secondSelfTestData }, transaction: transactionTwo })
|
await database.config.update({ value: 'd' }, { where: { id: configItemIds.secondSelfTestData }, transaction: transactionTwo })
|
||||||
})()
|
})()
|
||||||
])
|
])
|
||||||
})
|
}, { disableRetry: true })
|
||||||
})
|
}, { disableRetry: true })
|
||||||
|
|
||||||
throw new SerializationFeatureCheckException()
|
throw new SerializationFeatureCheckException()
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue