refactor: store w transaction

This commit is contained in:
Andres Aya
2023-04-20 08:14:11 -05:00
parent 28be45a9b4
commit 2b27416af0
2 changed files with 23 additions and 28 deletions

View File

@@ -82,7 +82,7 @@ export type SignalKeyStore = {
export type SignalKeyStoreWithTransaction = SignalKeyStore & { export type SignalKeyStoreWithTransaction = SignalKeyStore & {
isInTransaction: () => boolean isInTransaction: () => boolean
transaction(exec: () => Promise<void>): Promise<void> transaction<T>(exec: () => Promise<T>): Promise<T>
} }
export type TransactionCapabilityOptions = { export type TransactionCapabilityOptions = {
@@ -92,7 +92,7 @@ export type TransactionCapabilityOptions = {
export type SignalAuthState = { export type SignalAuthState = {
creds: SignalCreds creds: SignalCreds
keys: SignalKeyStore keys: SignalKeyStore | SignalKeyStoreWithTransaction
} }
export type AuthenticationState = { export type AuthenticationState = {

View File

@@ -93,32 +93,25 @@ export const addTransactionCapability = (
let transactionCache: SignalDataSet = { } let transactionCache: SignalDataSet = { }
let mutations: SignalDataSet = { } let mutations: SignalDataSet = { }
/**
* prefetches some data and stores in memory,
* useful if these data points will be used together often
* */
const prefetch = async<T extends keyof SignalDataTypeMap>(type: T, ids: string[]) => {
const dict = transactionCache[type]
const idsRequiringFetch = dict
? ids.filter(item => typeof dict[item] !== 'undefined')
: ids
// only fetch if there are any items to fetch
if(idsRequiringFetch.length) {
dbQueriesInTransaction += 1
const result = await state.get(type, idsRequiringFetch)
transactionCache[type] ||= {}
transactionCache[type] = Object.assign(
transactionCache[type]!,
result
)
}
}
return { return {
get: async(type, ids) => { get: async(type, ids) => {
if(inTransaction) { if(inTransaction) {
await prefetch(type, ids) const dict = transactionCache[type]
const idsRequiringFetch = dict
? ids.filter(item => typeof dict[item] !== 'undefined')
: ids
// only fetch if there are any items to fetch
if(idsRequiringFetch.length) {
dbQueriesInTransaction += 1
const result = await state.get(type, idsRequiringFetch)
transactionCache[type] ||= {}
Object.assign(
transactionCache[type]!,
result
)
}
return ids.reduce( return ids.reduce(
(dict, id) => { (dict, id) => {
const value = transactionCache[type]?.[id] const value = transactionCache[type]?.[id]
@@ -148,16 +141,17 @@ export const addTransactionCapability = (
} }
}, },
isInTransaction: () => inTransaction, isInTransaction: () => inTransaction,
transaction: async(work) => { async transaction(work) {
let result: Awaited<ReturnType<typeof work>>
// if we're already in a transaction, // if we're already in a transaction,
// just execute what needs to be executed -- no commit required // just execute what needs to be executed -- no commit required
if(inTransaction) { if(inTransaction) {
await work() result = await work()
} else { } else {
logger.trace('entering transaction') logger.trace('entering transaction')
inTransaction = true inTransaction = true
try { try {
await work() result = await work()
if(Object.keys(mutations).length) { if(Object.keys(mutations).length) {
logger.trace('committing transaction') logger.trace('committing transaction')
// retry mechanism to ensure we've some recovery // retry mechanism to ensure we've some recovery
@@ -184,6 +178,7 @@ export const addTransactionCapability = (
dbQueriesInTransaction = 0 dbQueriesInTransaction = 0
} }
} }
return result
} }
} }
} }