fix: auth store transactions + tests

This commit is contained in:
Andres Aya
2023-04-20 08:17:06 -05:00
parent 2b27416af0
commit d02066dec8
3 changed files with 146 additions and 16 deletions

View File

@@ -86,19 +86,20 @@ export const addTransactionCapability = (
logger: Logger,
{ maxCommitRetries, delayBetweenTriesMs }: TransactionCapabilityOptions
): SignalKeyStoreWithTransaction => {
let inTransaction = false
// number of queries made to the DB during the transaction
// only there for logging purposes
let dbQueriesInTransaction = 0
let transactionCache: SignalDataSet = { }
let mutations: SignalDataSet = { }
let transactionsInProgress = 0
return {
get: async(type, ids) => {
if(inTransaction) {
if(isInTransaction()) {
const dict = transactionCache[type]
const idsRequiringFetch = dict
? ids.filter(item => typeof dict[item] !== 'undefined')
? ids.filter(item => typeof dict[item] === 'undefined')
: ids
// only fetch if there are any items to fetch
if(idsRequiringFetch.length) {
@@ -127,7 +128,7 @@ export const addTransactionCapability = (
}
},
set: data => {
if(inTransaction) {
if(isInTransaction()) {
logger.trace({ types: Object.keys(data) }, 'caching in transaction')
for(const key in data) {
transactionCache[key] = transactionCache[key] || { }
@@ -140,18 +141,18 @@ export const addTransactionCapability = (
return state.set(data)
}
},
isInTransaction: () => inTransaction,
isInTransaction,
async transaction(work) {
let result: Awaited<ReturnType<typeof work>>
// if we're already in a transaction,
// just execute what needs to be executed -- no commit required
if(inTransaction) {
result = await work()
} else {
transactionsInProgress += 1
if(transactionsInProgress === 1) {
logger.trace('entering transaction')
inTransaction = true
try {
result = await work()
}
try {
result = await work()
// commit if this is the outermost transaction
if(transactionsInProgress === 1) {
if(Object.keys(mutations).length) {
logger.trace('committing transaction')
// retry mechanism to ensure we've some recovery
@@ -171,16 +172,23 @@ export const addTransactionCapability = (
} else {
logger.trace('no mutations in transaction')
}
} finally {
inTransaction = false
}
} finally {
transactionsInProgress -= 1
if(transactionsInProgress === 0) {
transactionCache = { }
mutations = { }
dbQueriesInTransaction = 0
}
}
return result
}
}
function isInTransaction() {
return transactionsInProgress > 0
}
}
export const initAuthCreds = (): AuthenticationCreds => {