diff options
author | Florian Dold <florian@dold.me> | 2024-04-23 03:09:40 +0200 |
---|---|---|
committer | Florian Dold <florian@dold.me> | 2024-04-23 03:09:40 +0200 |
commit | 1edc144b3595ae1ab6b8af7a43d26b811b2c2623 (patch) | |
tree | db552f6b4a351eb1d0dae902f4d504031852bda7 /packages/taler-wallet-core/src/backup/index.ts | |
parent | 4b69853c347071acb73efcde9d4969cf06d0dfcc (diff) | |
download | wallet-core-1edc144b3595ae1ab6b8af7a43d26b811b2c2623.tar.xz |
wallet-core: pass options object to all transactions
Diffstat (limited to 'packages/taler-wallet-core/src/backup/index.ts')
-rw-r--r-- | packages/taler-wallet-core/src/backup/index.ts | 361 |
1 files changed, 195 insertions, 166 deletions
diff --git a/packages/taler-wallet-core/src/backup/index.ts b/packages/taler-wallet-core/src/backup/index.ts index 5dccf1998..16b5488e7 100644 --- a/packages/taler-wallet-core/src/backup/index.ts +++ b/packages/taler-wallet-core/src/backup/index.ts @@ -183,7 +183,7 @@ async function runBackupCycleForProvider( args: BackupForProviderArgs, ): Promise<TaskRunResult> { const provider = await wex.db.runReadOnlyTx( - ["backupProviders"], + { storeNames: ["backupProviders"] }, async (tx) => { return tx.backupProviders.get(args.backupProviderBaseUrl); }, @@ -244,20 +244,23 @@ async function runBackupCycleForProvider( logger.trace(`sync response status: ${resp.status}`); if (resp.status === HttpStatusCode.NotModified) { - await wex.db.runReadWriteTx(["backupProviders"], async (tx) => { - const prov = await tx.backupProviders.get(provider.baseUrl); - if (!prov) { - return; - } - prov.lastBackupCycleTimestamp = timestampPreciseToDb( - TalerPreciseTimestamp.now(), - ); - prov.state = { - tag: BackupProviderStateTag.Ready, - nextBackupTimestamp: timestampPreciseToDb(getNextBackupTimestamp()), - }; - await tx.backupProviders.put(prov); - }); + await wex.db.runReadWriteTx( + { storeNames: ["backupProviders"] }, + async (tx) => { + const prov = await tx.backupProviders.get(provider.baseUrl); + if (!prov) { + return; + } + prov.lastBackupCycleTimestamp = timestampPreciseToDb( + TalerPreciseTimestamp.now(), + ); + prov.state = { + tag: BackupProviderStateTag.Ready, + nextBackupTimestamp: timestampPreciseToDb(getNextBackupTimestamp()), + }; + await tx.backupProviders.put(prov); + }, + ); removeAttentionRequest(wex, { entityId: provider.baseUrl, @@ -290,41 +293,47 @@ async function runBackupCycleForProvider( if (res === undefined) { //claimed - await wex.db.runReadWriteTx(["backupProviders"], async (tx) => { + await wex.db.runReadWriteTx( + { storeNames: ["backupProviders"] }, + async (tx) => { + const prov = await tx.backupProviders.get(provider.baseUrl); + if (!prov) { + logger.warn("backup provider not found anymore"); + return; + } + prov.shouldRetryFreshProposal = true; + prov.state = { + tag: BackupProviderStateTag.Retrying, + }; + await tx.backupProviders.put(prov); + }, + ); + + throw Error("not implemented"); + // return { + // type: TaskRunResultType.Pending, + // }; + } + const result = res; + + await wex.db.runReadWriteTx( + { storeNames: ["backupProviders"] }, + async (tx) => { const prov = await tx.backupProviders.get(provider.baseUrl); if (!prov) { logger.warn("backup provider not found anymore"); return; } - prov.shouldRetryFreshProposal = true; + // const opId = TaskIdentifiers.forBackup(prov); + // await scheduleRetryInTx(ws, tx, opId); + prov.currentPaymentProposalId = result.proposalId; + prov.shouldRetryFreshProposal = false; prov.state = { tag: BackupProviderStateTag.Retrying, }; await tx.backupProviders.put(prov); - }); - - throw Error("not implemented"); - // return { - // type: TaskRunResultType.Pending, - // }; - } - const result = res; - - await wex.db.runReadWriteTx(["backupProviders"], async (tx) => { - const prov = await tx.backupProviders.get(provider.baseUrl); - if (!prov) { - logger.warn("backup provider not found anymore"); - return; - } - // const opId = TaskIdentifiers.forBackup(prov); - // await scheduleRetryInTx(ws, tx, opId); - prov.currentPaymentProposalId = result.proposalId; - prov.shouldRetryFreshProposal = false; - prov.state = { - tag: BackupProviderStateTag.Retrying, - }; - await tx.backupProviders.put(prov); - }); + }, + ); addAttentionRequest( wex, @@ -343,21 +352,24 @@ async function runBackupCycleForProvider( } if (resp.status === HttpStatusCode.NoContent) { - await wex.db.runReadWriteTx(["backupProviders"], async (tx) => { - const prov = await tx.backupProviders.get(provider.baseUrl); - if (!prov) { - return; - } - prov.lastBackupHash = encodeCrock(currentBackupHash); - prov.lastBackupCycleTimestamp = timestampPreciseToDb( - TalerPreciseTimestamp.now(), - ); - prov.state = { - tag: BackupProviderStateTag.Ready, - nextBackupTimestamp: timestampPreciseToDb(getNextBackupTimestamp()), - }; - await tx.backupProviders.put(prov); - }); + await wex.db.runReadWriteTx( + { storeNames: ["backupProviders"] }, + async (tx) => { + const prov = await tx.backupProviders.get(provider.baseUrl); + if (!prov) { + return; + } + prov.lastBackupHash = encodeCrock(currentBackupHash); + prov.lastBackupCycleTimestamp = timestampPreciseToDb( + TalerPreciseTimestamp.now(), + ); + prov.state = { + tag: BackupProviderStateTag.Ready, + nextBackupTimestamp: timestampPreciseToDb(getNextBackupTimestamp()), + }; + await tx.backupProviders.put(prov); + }, + ); removeAttentionRequest(wex, { entityId: provider.baseUrl, @@ -376,22 +388,25 @@ async function runBackupCycleForProvider( // const blob = await decryptBackup(backupConfig, backupEnc); // FIXME: Re-implement backup import with merging // await importBackup(ws, blob, cryptoData); - await wex.db.runReadWriteTx(["backupProviders"], async (tx) => { - const prov = await tx.backupProviders.get(provider.baseUrl); - if (!prov) { - logger.warn("backup provider not found anymore"); - return; - } - prov.lastBackupHash = encodeCrock(hash(backupEnc)); - // FIXME: Allocate error code for this situation? - // FIXME: Add operation retry record! - const opId = TaskIdentifiers.forBackup(prov); - //await scheduleRetryInTx(ws, tx, opId); - prov.state = { - tag: BackupProviderStateTag.Retrying, - }; - await tx.backupProviders.put(prov); - }); + await wex.db.runReadWriteTx( + { storeNames: ["backupProviders"] }, + async (tx) => { + const prov = await tx.backupProviders.get(provider.baseUrl); + if (!prov) { + logger.warn("backup provider not found anymore"); + return; + } + prov.lastBackupHash = encodeCrock(hash(backupEnc)); + // FIXME: Allocate error code for this situation? + // FIXME: Add operation retry record! + const opId = TaskIdentifiers.forBackup(prov); + //await scheduleRetryInTx(ws, tx, opId); + prov.state = { + tag: BackupProviderStateTag.Retrying, + }; + await tx.backupProviders.put(prov); + }, + ); logger.info("processed existing backup"); // Now upload our own, merged backup. return await runBackupCycleForProvider(wex, args); @@ -414,7 +429,7 @@ export async function processBackupForProvider( backupProviderBaseUrl: string, ): Promise<TaskRunResult> { const provider = await wex.db.runReadOnlyTx( - ["backupProviders"], + { storeNames: ["backupProviders"] }, async (tx) => { return await tx.backupProviders.get(backupProviderBaseUrl); }, @@ -444,9 +459,12 @@ export async function removeBackupProvider( wex: WalletExecutionContext, req: RemoveBackupProviderRequest, ): Promise<void> { - await wex.db.runReadWriteTx(["backupProviders"], async (tx) => { - await tx.backupProviders.delete(req.provider); - }); + await wex.db.runReadWriteTx( + { storeNames: ["backupProviders"] }, + async (tx) => { + await tx.backupProviders.delete(req.provider); + }, + ); } export interface RunBackupCycleRequest { @@ -473,7 +491,7 @@ export async function runBackupCycle( req: RunBackupCycleRequest, ): Promise<void> { const providers = await wex.db.runReadOnlyTx( - ["backupProviders"], + { storeNames: ["backupProviders"] }, async (tx) => { if (req.providers) { const rs = await Promise.all( @@ -553,56 +571,64 @@ export async function addBackupProvider( logger.info(`adding backup provider ${j2s(req)}`); await provideBackupState(wex); const canonUrl = canonicalizeBaseUrl(req.backupProviderBaseUrl); - await wex.db.runReadWriteTx(["backupProviders"], async (tx) => { - const oldProv = await tx.backupProviders.get(canonUrl); - if (oldProv) { - logger.info("old backup provider found"); + await wex.db.runReadWriteTx( + { storeNames: ["backupProviders"] }, + async (tx) => { + const oldProv = await tx.backupProviders.get(canonUrl); + if (oldProv) { + logger.info("old backup provider found"); + if (req.activate) { + oldProv.state = { + tag: BackupProviderStateTag.Ready, + nextBackupTimestamp: timestampPreciseToDb( + TalerPreciseTimestamp.now(), + ), + }; + logger.info("setting existing backup provider to active"); + await tx.backupProviders.put(oldProv); + } + return; + } + }, + ); + const termsUrl = new URL("config", canonUrl); + const resp = await wex.http.fetch(termsUrl.href); + const terms = await readSuccessResponseJsonOrThrow( + resp, + codecForSyncTermsOfServiceResponse(), + ); + await wex.db.runReadWriteTx( + { storeNames: ["backupProviders"] }, + async (tx) => { + let state: BackupProviderState; + //FIXME: what is the difference provisional and ready? if (req.activate) { - oldProv.state = { + state = { tag: BackupProviderStateTag.Ready, nextBackupTimestamp: timestampPreciseToDb( TalerPreciseTimestamp.now(), ), }; - logger.info("setting existing backup provider to active"); - await tx.backupProviders.put(oldProv); + } else { + state = { + tag: BackupProviderStateTag.Provisional, + }; } - return; - } - }); - const termsUrl = new URL("config", canonUrl); - const resp = await wex.http.fetch(termsUrl.href); - const terms = await readSuccessResponseJsonOrThrow( - resp, - codecForSyncTermsOfServiceResponse(), + await tx.backupProviders.put({ + state, + name: req.name, + terms: { + annualFee: terms.annual_fee, + storageLimitInMegabytes: terms.storage_limit_in_megabytes, + supportedProtocolVersion: terms.version, + }, + shouldRetryFreshProposal: false, + paymentProposalIds: [], + baseUrl: canonUrl, + uids: [encodeCrock(getRandomBytes(32))], + }); + }, ); - await wex.db.runReadWriteTx(["backupProviders"], async (tx) => { - let state: BackupProviderState; - //FIXME: what is the difference provisional and ready? - if (req.activate) { - state = { - tag: BackupProviderStateTag.Ready, - nextBackupTimestamp: timestampPreciseToDb(TalerPreciseTimestamp.now()), - }; - } else { - state = { - tag: BackupProviderStateTag.Provisional, - }; - } - await tx.backupProviders.put({ - state, - name: req.name, - terms: { - annualFee: terms.annual_fee, - storageLimitInMegabytes: terms.storage_limit_in_megabytes, - supportedProtocolVersion: terms.version, - }, - shouldRetryFreshProposal: false, - paymentProposalIds: [], - baseUrl: canonUrl, - uids: [encodeCrock(getRandomBytes(32))], - }); - }); return await runFirstBackupCycleForProvider(wex, { backupProviderBaseUrl: canonUrl, @@ -706,7 +732,7 @@ export async function getBackupInfo( ): Promise<BackupInfo> { const backupConfig = await provideBackupState(wex); const providerRecords = await wex.db.runReadOnlyTx( - ["backupProviders", "operationRetries"], + { storeNames: ["backupProviders", "operationRetries"] }, async (tx) => { return await tx.backupProviders.iter().mapAsync(async (bp) => { const opId = TaskIdentifiers.forBackup(bp); @@ -752,7 +778,7 @@ export async function getBackupRecovery( ): Promise<BackupRecovery> { const bs = await provideBackupState(wex); const providers = await wex.db.runReadOnlyTx( - ["backupProviders"], + { storeNames: ["backupProviders"] }, async (tx) => { return await tx.backupProviders.iter().toArray(); }, @@ -774,48 +800,51 @@ async function backupRecoveryTheirs( wex: WalletExecutionContext, br: BackupRecovery, ) { - await wex.db.runReadWriteTx(["backupProviders", "config"], async (tx) => { - let backupStateEntry: ConfigRecord | undefined = await tx.config.get( - ConfigRecordKey.WalletBackupState, - ); - checkDbInvariant(!!backupStateEntry); - checkDbInvariant( - backupStateEntry.key === ConfigRecordKey.WalletBackupState, - ); - backupStateEntry.value.lastBackupNonce = undefined; - backupStateEntry.value.lastBackupTimestamp = undefined; - backupStateEntry.value.lastBackupCheckTimestamp = undefined; - backupStateEntry.value.lastBackupPlainHash = undefined; - backupStateEntry.value.walletRootPriv = br.walletRootPriv; - backupStateEntry.value.walletRootPub = encodeCrock( - eddsaGetPublic(decodeCrock(br.walletRootPriv)), - ); - await tx.config.put(backupStateEntry); - for (const prov of br.providers) { - const existingProv = await tx.backupProviders.get(prov.url); - if (!existingProv) { - await tx.backupProviders.put({ - baseUrl: prov.url, - name: prov.name, - paymentProposalIds: [], - shouldRetryFreshProposal: false, - state: { - tag: BackupProviderStateTag.Ready, - nextBackupTimestamp: timestampPreciseToDb( - TalerPreciseTimestamp.now(), - ), - }, - uids: [encodeCrock(getRandomBytes(32))], - }); + await wex.db.runReadWriteTx( + { storeNames: ["backupProviders", "config"] }, + async (tx) => { + let backupStateEntry: ConfigRecord | undefined = await tx.config.get( + ConfigRecordKey.WalletBackupState, + ); + checkDbInvariant(!!backupStateEntry); + checkDbInvariant( + backupStateEntry.key === ConfigRecordKey.WalletBackupState, + ); + backupStateEntry.value.lastBackupNonce = undefined; + backupStateEntry.value.lastBackupTimestamp = undefined; + backupStateEntry.value.lastBackupCheckTimestamp = undefined; + backupStateEntry.value.lastBackupPlainHash = undefined; + backupStateEntry.value.walletRootPriv = br.walletRootPriv; + backupStateEntry.value.walletRootPub = encodeCrock( + eddsaGetPublic(decodeCrock(br.walletRootPriv)), + ); + await tx.config.put(backupStateEntry); + for (const prov of br.providers) { + const existingProv = await tx.backupProviders.get(prov.url); + if (!existingProv) { + await tx.backupProviders.put({ + baseUrl: prov.url, + name: prov.name, + paymentProposalIds: [], + shouldRetryFreshProposal: false, + state: { + tag: BackupProviderStateTag.Ready, + nextBackupTimestamp: timestampPreciseToDb( + TalerPreciseTimestamp.now(), + ), + }, + uids: [encodeCrock(getRandomBytes(32))], + }); + } } - } - const providers = await tx.backupProviders.iter().toArray(); - for (const prov of providers) { - prov.lastBackupCycleTimestamp = undefined; - prov.lastBackupHash = undefined; - await tx.backupProviders.put(prov); - } - }); + const providers = await tx.backupProviders.iter().toArray(); + for (const prov of providers) { + prov.lastBackupCycleTimestamp = undefined; + prov.lastBackupHash = undefined; + await tx.backupProviders.put(prov); + } + }, + ); } async function backupRecoveryOurs( @@ -831,7 +860,7 @@ export async function loadBackupRecovery( ): Promise<void> { const bs = await provideBackupState(wex); const providers = await wex.db.runReadOnlyTx( - ["backupProviders"], + { storeNames: ["backupProviders"] }, async (tx) => { return await tx.backupProviders.iter().toArray(); }, @@ -879,7 +908,7 @@ export async function provideBackupState( wex: WalletExecutionContext, ): Promise<WalletBackupConfState> { const bs: ConfigRecord | undefined = await wex.db.runReadOnlyTx( - ["config"], + { storeNames: ["config"] }, async (tx) => { return await tx.config.get(ConfigRecordKey.WalletBackupState); }, @@ -895,7 +924,7 @@ export async function provideBackupState( // FIXME: device ID should be configured when wallet is initialized // and be based on hostname const deviceId = `wallet-core-${encodeCrock(d)}`; - return await wex.db.runReadWriteTx(["config"], async (tx) => { + return await wex.db.runReadWriteTx({ storeNames: ["config"] }, async (tx) => { let backupStateEntry: ConfigRecord | undefined = await tx.config.get( ConfigRecordKey.WalletBackupState, ); @@ -933,7 +962,7 @@ export async function setWalletDeviceId( deviceId: string, ): Promise<void> { await provideBackupState(wex); - await wex.db.runReadWriteTx(["config"], async (tx) => { + await wex.db.runReadWriteTx({ storeNames: ["config"] }, async (tx) => { let backupStateEntry: ConfigRecord | undefined = await tx.config.get( ConfigRecordKey.WalletBackupState, ); |