2019-12-02 00:42:40 +01:00
|
|
|
/*
|
|
|
|
This file is part of GNU Taler
|
|
|
|
(C) 2019 GNUnet e.V.
|
|
|
|
|
|
|
|
GNU Taler is free software; you can redistribute it and/or modify it under the
|
|
|
|
terms of the GNU General Public License as published by the Free Software
|
|
|
|
Foundation; either version 3, or (at your option) any later version.
|
|
|
|
|
|
|
|
GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
|
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
|
|
|
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License along with
|
|
|
|
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
|
|
|
*/
|
|
|
|
|
2021-06-25 13:27:06 +02:00
|
|
|
/**
|
|
|
|
* Derive pending tasks from the wallet database.
|
|
|
|
*/
|
|
|
|
|
2019-12-02 17:35:47 +01:00
|
|
|
/**
|
|
|
|
* Imports.
|
|
|
|
*/
|
|
|
|
import {
|
|
|
|
ProposalStatus,
|
2020-09-08 22:48:03 +02:00
|
|
|
AbortStatus,
|
2021-06-09 15:14:17 +02:00
|
|
|
WalletStoresV1,
|
2021-06-25 13:27:06 +02:00
|
|
|
BackupProviderStateTag,
|
2021-08-24 14:25:46 +02:00
|
|
|
RefreshCoinStatus,
|
2022-01-11 21:00:12 +01:00
|
|
|
OperationStatus,
|
2022-09-21 20:46:45 +02:00
|
|
|
OperationStatusRange,
|
2021-03-17 17:56:37 +01:00
|
|
|
} from "../db.js";
|
2019-12-15 19:08:07 +01:00
|
|
|
import {
|
|
|
|
PendingOperationsResponse,
|
2021-06-25 13:27:06 +02:00
|
|
|
PendingTaskType,
|
2021-06-14 16:08:58 +02:00
|
|
|
} from "../pending-types.js";
|
2022-03-18 15:32:41 +01:00
|
|
|
import { AbsoluteTime } from "@gnu-taler/taler-util";
|
2022-03-23 13:11:36 +01:00
|
|
|
import { InternalWalletState } from "../internal-wallet-state.js";
|
2021-06-09 15:14:17 +02:00
|
|
|
import { GetReadOnlyAccess } from "../util/query.js";
|
2022-09-05 18:12:30 +02:00
|
|
|
import { RetryTags } from "../util/retries.js";
|
|
|
|
import { Wallet } from "../wallet.js";
|
2022-09-21 20:46:45 +02:00
|
|
|
import { GlobalIDB } from "@gnu-taler/idb-bridge";
|
2019-12-02 00:42:40 +01:00
|
|
|
|
2019-12-05 19:38:19 +01:00
|
|
|
async function gatherExchangePending(
|
2021-06-09 15:14:17 +02:00
|
|
|
tx: GetReadOnlyAccess<{
|
|
|
|
exchanges: typeof WalletStoresV1.exchanges;
|
|
|
|
exchangeDetails: typeof WalletStoresV1.exchangeDetails;
|
2022-09-05 18:12:30 +02:00
|
|
|
operationRetries: typeof WalletStoresV1.operationRetries;
|
2021-06-09 15:14:17 +02:00
|
|
|
}>,
|
2022-03-18 15:32:41 +01:00
|
|
|
now: AbsoluteTime,
|
2019-12-05 19:38:19 +01:00
|
|
|
resp: PendingOperationsResponse,
|
|
|
|
): Promise<void> {
|
2022-10-05 18:31:56 +02:00
|
|
|
// FIXME: We should do a range query here based on the update time.
|
2022-09-05 18:12:30 +02:00
|
|
|
await tx.exchanges.iter().forEachAsync(async (exch) => {
|
|
|
|
const opTag = RetryTags.forExchangeUpdate(exch);
|
|
|
|
let opr = await tx.operationRetries.get(opTag);
|
2021-06-10 16:32:37 +02:00
|
|
|
resp.pendingOperations.push({
|
2021-06-25 13:27:06 +02:00
|
|
|
type: PendingTaskType.ExchangeUpdate,
|
2022-09-05 18:12:30 +02:00
|
|
|
id: opTag,
|
2021-06-10 16:32:37 +02:00
|
|
|
givesLifeness: false,
|
2022-03-29 13:47:32 +02:00
|
|
|
timestampDue:
|
2022-09-05 18:12:30 +02:00
|
|
|
opr?.retryInfo.nextRetry ?? AbsoluteTime.fromTimestamp(exch.nextUpdate),
|
|
|
|
exchangeBaseUrl: exch.baseUrl,
|
|
|
|
lastError: opr?.lastError,
|
2021-06-10 16:32:37 +02:00
|
|
|
});
|
|
|
|
|
2022-05-31 15:44:22 +02:00
|
|
|
// We only schedule a check for auto-refresh if the exchange update
|
|
|
|
// was successful.
|
2022-09-05 18:12:30 +02:00
|
|
|
if (!opr?.lastError) {
|
2022-05-31 15:44:22 +02:00
|
|
|
resp.pendingOperations.push({
|
|
|
|
type: PendingTaskType.ExchangeCheckRefresh,
|
2022-09-05 18:12:30 +02:00
|
|
|
id: RetryTags.forExchangeCheckRefresh(exch),
|
|
|
|
timestampDue: AbsoluteTime.fromTimestamp(exch.nextRefreshCheck),
|
2022-05-31 15:44:22 +02:00
|
|
|
givesLifeness: false,
|
2022-09-05 18:12:30 +02:00
|
|
|
exchangeBaseUrl: exch.baseUrl,
|
2022-05-31 15:44:22 +02:00
|
|
|
});
|
|
|
|
}
|
2019-12-05 19:38:19 +01:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
async function gatherRefreshPending(
|
2022-09-05 18:12:30 +02:00
|
|
|
tx: GetReadOnlyAccess<{
|
|
|
|
refreshGroups: typeof WalletStoresV1.refreshGroups;
|
|
|
|
operationRetries: typeof WalletStoresV1.operationRetries;
|
|
|
|
}>,
|
2022-03-18 15:32:41 +01:00
|
|
|
now: AbsoluteTime,
|
2019-12-05 19:38:19 +01:00
|
|
|
resp: PendingOperationsResponse,
|
|
|
|
): Promise<void> {
|
2022-01-13 12:08:31 +01:00
|
|
|
const refreshGroups = await tx.refreshGroups.indexes.byStatus.getAll(
|
|
|
|
OperationStatus.Pending,
|
|
|
|
);
|
|
|
|
for (const r of refreshGroups) {
|
|
|
|
if (r.timestampFinished) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (r.frozen) {
|
|
|
|
return;
|
|
|
|
}
|
2022-09-05 18:12:30 +02:00
|
|
|
const opId = RetryTags.forRefresh(r);
|
|
|
|
const retryRecord = await tx.operationRetries.get(opId);
|
|
|
|
|
2022-01-13 12:08:31 +01:00
|
|
|
resp.pendingOperations.push({
|
|
|
|
type: PendingTaskType.Refresh,
|
2022-09-05 18:12:30 +02:00
|
|
|
id: opId,
|
2022-01-13 12:08:31 +01:00
|
|
|
givesLifeness: true,
|
2022-09-05 18:12:30 +02:00
|
|
|
timestampDue: retryRecord?.retryInfo.nextRetry ?? AbsoluteTime.now(),
|
2022-01-13 12:08:31 +01:00
|
|
|
refreshGroupId: r.refreshGroupId,
|
|
|
|
finishedPerCoin: r.statusPerCoin.map(
|
|
|
|
(x) => x === RefreshCoinStatus.Finished,
|
|
|
|
),
|
2022-09-05 18:12:30 +02:00
|
|
|
retryInfo: retryRecord?.retryInfo,
|
2019-12-05 19:38:19 +01:00
|
|
|
});
|
2022-01-13 12:08:31 +01:00
|
|
|
}
|
2019-12-05 19:38:19 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
async function gatherWithdrawalPending(
|
2021-06-09 15:14:17 +02:00
|
|
|
tx: GetReadOnlyAccess<{
|
|
|
|
withdrawalGroups: typeof WalletStoresV1.withdrawalGroups;
|
2021-06-09 15:26:18 +02:00
|
|
|
planchets: typeof WalletStoresV1.planchets;
|
2022-09-05 18:12:30 +02:00
|
|
|
operationRetries: typeof WalletStoresV1.operationRetries;
|
2021-06-09 15:14:17 +02:00
|
|
|
}>,
|
2022-03-18 15:32:41 +01:00
|
|
|
now: AbsoluteTime,
|
2019-12-05 19:38:19 +01:00
|
|
|
resp: PendingOperationsResponse,
|
|
|
|
): Promise<void> {
|
2022-01-13 12:08:31 +01:00
|
|
|
const wsrs = await tx.withdrawalGroups.indexes.byStatus.getAll(
|
2022-09-21 20:46:45 +02:00
|
|
|
GlobalIDB.KeyRange.bound(
|
|
|
|
OperationStatusRange.ACTIVE_START,
|
|
|
|
OperationStatusRange.ACTIVE_END,
|
|
|
|
),
|
2022-01-13 12:08:31 +01:00
|
|
|
);
|
|
|
|
for (const wsr of wsrs) {
|
|
|
|
if (wsr.timestampFinish) {
|
|
|
|
return;
|
|
|
|
}
|
2022-09-05 18:12:30 +02:00
|
|
|
const opTag = RetryTags.forWithdrawal(wsr);
|
|
|
|
let opr = await tx.operationRetries.get(opTag);
|
|
|
|
const now = AbsoluteTime.now();
|
|
|
|
if (!opr) {
|
|
|
|
opr = {
|
|
|
|
id: opTag,
|
|
|
|
retryInfo: {
|
|
|
|
firstTry: now,
|
|
|
|
nextRetry: now,
|
|
|
|
retryCounter: 0,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
}
|
2022-01-13 12:08:31 +01:00
|
|
|
resp.pendingOperations.push({
|
|
|
|
type: PendingTaskType.Withdraw,
|
2022-09-05 18:12:30 +02:00
|
|
|
id: opTag,
|
2022-01-13 12:08:31 +01:00
|
|
|
givesLifeness: true,
|
2022-09-05 18:12:30 +02:00
|
|
|
timestampDue: opr.retryInfo?.nextRetry ?? AbsoluteTime.now(),
|
2022-01-13 12:08:31 +01:00
|
|
|
withdrawalGroupId: wsr.withdrawalGroupId,
|
2022-09-05 18:12:30 +02:00
|
|
|
lastError: opr.lastError,
|
|
|
|
retryInfo: opr.retryInfo,
|
2019-12-05 19:38:19 +01:00
|
|
|
});
|
2022-01-13 12:08:31 +01:00
|
|
|
}
|
2019-12-05 19:38:19 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
async function gatherProposalPending(
|
2022-09-05 18:12:30 +02:00
|
|
|
tx: GetReadOnlyAccess<{
|
|
|
|
proposals: typeof WalletStoresV1.proposals;
|
|
|
|
operationRetries: typeof WalletStoresV1.operationRetries;
|
|
|
|
}>,
|
2022-03-18 15:32:41 +01:00
|
|
|
now: AbsoluteTime,
|
2019-12-05 19:38:19 +01:00
|
|
|
resp: PendingOperationsResponse,
|
|
|
|
): Promise<void> {
|
2022-09-05 18:12:30 +02:00
|
|
|
await tx.proposals.iter().forEachAsync(async (proposal) => {
|
2022-03-08 23:09:20 +01:00
|
|
|
if (proposal.proposalStatus == ProposalStatus.Proposed) {
|
2021-06-10 16:32:37 +02:00
|
|
|
// Nothing to do, user needs to choose.
|
2022-03-08 23:09:20 +01:00
|
|
|
} else if (proposal.proposalStatus == ProposalStatus.Downloading) {
|
2022-09-05 18:12:30 +02:00
|
|
|
const opId = RetryTags.forProposalClaim(proposal);
|
|
|
|
const retryRecord = await tx.operationRetries.get(opId);
|
|
|
|
const timestampDue =
|
|
|
|
retryRecord?.retryInfo?.nextRetry ?? AbsoluteTime.now();
|
2019-12-05 19:38:19 +01:00
|
|
|
resp.pendingOperations.push({
|
2021-06-25 13:27:06 +02:00
|
|
|
type: PendingTaskType.ProposalDownload,
|
2022-09-05 18:12:30 +02:00
|
|
|
id: opId,
|
2019-12-05 19:38:19 +01:00
|
|
|
givesLifeness: true,
|
2021-06-11 11:15:08 +02:00
|
|
|
timestampDue,
|
2019-12-06 12:47:28 +01:00
|
|
|
merchantBaseUrl: proposal.merchantBaseUrl,
|
|
|
|
orderId: proposal.orderId,
|
2019-12-05 19:38:19 +01:00
|
|
|
proposalId: proposal.proposalId,
|
|
|
|
proposalTimestamp: proposal.timestamp,
|
2022-09-05 18:12:30 +02:00
|
|
|
lastError: retryRecord?.lastError,
|
|
|
|
retryInfo: retryRecord?.retryInfo,
|
2019-12-05 19:38:19 +01:00
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2021-08-07 17:59:06 +02:00
|
|
|
async function gatherDepositPending(
|
2022-09-05 18:12:30 +02:00
|
|
|
tx: GetReadOnlyAccess<{
|
|
|
|
depositGroups: typeof WalletStoresV1.depositGroups;
|
|
|
|
operationRetries: typeof WalletStoresV1.operationRetries;
|
|
|
|
}>,
|
2022-03-18 15:32:41 +01:00
|
|
|
now: AbsoluteTime,
|
2021-08-07 17:59:06 +02:00
|
|
|
resp: PendingOperationsResponse,
|
|
|
|
): Promise<void> {
|
2022-01-13 12:08:31 +01:00
|
|
|
const dgs = await tx.depositGroups.indexes.byStatus.getAll(
|
|
|
|
OperationStatus.Pending,
|
|
|
|
);
|
|
|
|
for (const dg of dgs) {
|
|
|
|
if (dg.timestampFinished) {
|
|
|
|
return;
|
|
|
|
}
|
2022-09-05 18:12:30 +02:00
|
|
|
const opId = RetryTags.forDeposit(dg);
|
|
|
|
const retryRecord = await tx.operationRetries.get(opId);
|
|
|
|
const timestampDue = retryRecord?.retryInfo.nextRetry ?? AbsoluteTime.now();
|
2022-01-13 12:08:31 +01:00
|
|
|
resp.pendingOperations.push({
|
|
|
|
type: PendingTaskType.Deposit,
|
2022-09-05 18:12:30 +02:00
|
|
|
id: opId,
|
2022-01-13 12:08:31 +01:00
|
|
|
givesLifeness: true,
|
|
|
|
timestampDue,
|
|
|
|
depositGroupId: dg.depositGroupId,
|
2022-09-05 18:12:30 +02:00
|
|
|
lastError: retryRecord?.lastError,
|
|
|
|
retryInfo: retryRecord?.retryInfo,
|
2021-08-07 17:59:06 +02:00
|
|
|
});
|
2022-01-13 12:08:31 +01:00
|
|
|
}
|
2021-08-07 17:59:06 +02:00
|
|
|
}
|
|
|
|
|
2019-12-05 19:38:19 +01:00
|
|
|
async function gatherTipPending(
|
2022-09-05 18:12:30 +02:00
|
|
|
tx: GetReadOnlyAccess<{
|
|
|
|
tips: typeof WalletStoresV1.tips;
|
|
|
|
operationRetries: typeof WalletStoresV1.operationRetries;
|
|
|
|
}>,
|
2022-03-18 15:32:41 +01:00
|
|
|
now: AbsoluteTime,
|
2019-12-05 19:38:19 +01:00
|
|
|
resp: PendingOperationsResponse,
|
|
|
|
): Promise<void> {
|
2022-09-05 18:12:30 +02:00
|
|
|
await tx.tips.iter().forEachAsync(async (tip) => {
|
|
|
|
// FIXME: The tip record needs a proper status field!
|
2020-09-08 16:24:23 +02:00
|
|
|
if (tip.pickedUpTimestamp) {
|
2019-12-05 19:38:19 +01:00
|
|
|
return;
|
|
|
|
}
|
2022-09-05 18:12:30 +02:00
|
|
|
const opId = RetryTags.forTipPickup(tip);
|
|
|
|
const retryRecord = await tx.operationRetries.get(opId);
|
2019-12-16 12:53:22 +01:00
|
|
|
if (tip.acceptedTimestamp) {
|
2019-12-05 19:38:19 +01:00
|
|
|
resp.pendingOperations.push({
|
2021-06-25 13:27:06 +02:00
|
|
|
type: PendingTaskType.TipPickup,
|
2022-09-05 18:12:30 +02:00
|
|
|
id: opId,
|
2019-12-05 19:38:19 +01:00
|
|
|
givesLifeness: true,
|
2022-09-05 18:12:30 +02:00
|
|
|
timestampDue: retryRecord?.retryInfo.nextRetry ?? AbsoluteTime.now(),
|
2019-12-05 19:38:19 +01:00
|
|
|
merchantBaseUrl: tip.merchantBaseUrl,
|
2020-09-08 14:10:47 +02:00
|
|
|
tipId: tip.walletTipId,
|
2019-12-05 19:38:19 +01:00
|
|
|
merchantTipId: tip.merchantTipId,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
async function gatherPurchasePending(
|
2022-09-05 18:12:30 +02:00
|
|
|
tx: GetReadOnlyAccess<{
|
|
|
|
purchases: typeof WalletStoresV1.purchases;
|
|
|
|
operationRetries: typeof WalletStoresV1.operationRetries;
|
|
|
|
}>,
|
2022-03-18 15:32:41 +01:00
|
|
|
now: AbsoluteTime,
|
2019-12-05 19:38:19 +01:00
|
|
|
resp: PendingOperationsResponse,
|
|
|
|
): Promise<void> {
|
2022-09-05 18:12:30 +02:00
|
|
|
// FIXME: Only iter purchases with some "active" flag!
|
|
|
|
await tx.purchases.iter().forEachAsync(async (pr) => {
|
2021-08-24 15:08:34 +02:00
|
|
|
if (
|
|
|
|
pr.paymentSubmitPending &&
|
|
|
|
pr.abortStatus === AbortStatus.None &&
|
|
|
|
!pr.payFrozen
|
|
|
|
) {
|
2022-09-05 18:12:30 +02:00
|
|
|
const payOpId = RetryTags.forPay(pr);
|
|
|
|
const payRetryRecord = await tx.operationRetries.get(payOpId);
|
|
|
|
|
|
|
|
const timestampDue =
|
|
|
|
payRetryRecord?.retryInfo.nextRetry ?? AbsoluteTime.now();
|
2021-06-10 16:32:37 +02:00
|
|
|
resp.pendingOperations.push({
|
2021-06-25 13:27:06 +02:00
|
|
|
type: PendingTaskType.Pay,
|
2022-09-05 18:12:30 +02:00
|
|
|
id: payOpId,
|
2021-06-10 16:32:37 +02:00
|
|
|
givesLifeness: true,
|
2021-06-11 13:18:33 +02:00
|
|
|
timestampDue,
|
2021-06-10 16:32:37 +02:00
|
|
|
isReplay: false,
|
|
|
|
proposalId: pr.proposalId,
|
2022-09-05 18:12:30 +02:00
|
|
|
retryInfo: payRetryRecord?.retryInfo,
|
|
|
|
lastError: payRetryRecord?.lastError,
|
2021-06-10 16:32:37 +02:00
|
|
|
});
|
2019-12-05 19:38:19 +01:00
|
|
|
}
|
2020-09-08 22:48:03 +02:00
|
|
|
if (pr.refundQueryRequested) {
|
2022-09-05 18:12:30 +02:00
|
|
|
const refundQueryOpId = RetryTags.forRefundQuery(pr);
|
|
|
|
const refundQueryRetryRecord = await tx.operationRetries.get(
|
|
|
|
refundQueryOpId,
|
|
|
|
);
|
2021-06-10 16:32:37 +02:00
|
|
|
resp.pendingOperations.push({
|
2021-06-25 13:27:06 +02:00
|
|
|
type: PendingTaskType.RefundQuery,
|
2022-09-05 18:12:30 +02:00
|
|
|
id: refundQueryOpId,
|
2021-06-10 16:32:37 +02:00
|
|
|
givesLifeness: true,
|
2022-09-05 18:12:30 +02:00
|
|
|
timestampDue:
|
|
|
|
refundQueryRetryRecord?.retryInfo.nextRetry ?? AbsoluteTime.now(),
|
2021-06-10 16:32:37 +02:00
|
|
|
proposalId: pr.proposalId,
|
2022-09-05 18:12:30 +02:00
|
|
|
retryInfo: refundQueryRetryRecord?.retryInfo,
|
|
|
|
lastError: refundQueryRetryRecord?.lastError,
|
2021-06-10 16:32:37 +02:00
|
|
|
});
|
2019-12-06 00:24:34 +01:00
|
|
|
}
|
2019-12-05 19:38:19 +01:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2020-03-11 20:14:28 +01:00
|
|
|
async function gatherRecoupPending(
|
2022-09-05 18:12:30 +02:00
|
|
|
tx: GetReadOnlyAccess<{
|
|
|
|
recoupGroups: typeof WalletStoresV1.recoupGroups;
|
|
|
|
operationRetries: typeof WalletStoresV1.operationRetries;
|
|
|
|
}>,
|
2022-03-18 15:32:41 +01:00
|
|
|
now: AbsoluteTime,
|
2020-03-11 20:14:28 +01:00
|
|
|
resp: PendingOperationsResponse,
|
|
|
|
): Promise<void> {
|
2022-09-05 18:12:30 +02:00
|
|
|
await tx.recoupGroups.iter().forEachAsync(async (rg) => {
|
2020-03-11 20:14:28 +01:00
|
|
|
if (rg.timestampFinished) {
|
|
|
|
return;
|
|
|
|
}
|
2022-09-05 18:12:30 +02:00
|
|
|
const opId = RetryTags.forRecoup(rg);
|
|
|
|
const retryRecord = await tx.operationRetries.get(opId);
|
2020-03-11 20:14:28 +01:00
|
|
|
resp.pendingOperations.push({
|
2021-06-25 13:27:06 +02:00
|
|
|
type: PendingTaskType.Recoup,
|
2022-09-05 18:12:30 +02:00
|
|
|
id: opId,
|
2020-03-11 20:14:28 +01:00
|
|
|
givesLifeness: true,
|
2022-09-05 18:12:30 +02:00
|
|
|
timestampDue: retryRecord?.retryInfo.nextRetry ?? AbsoluteTime.now(),
|
2020-03-11 20:14:28 +01:00
|
|
|
recoupGroupId: rg.recoupGroupId,
|
2022-09-05 18:12:30 +02:00
|
|
|
retryInfo: retryRecord?.retryInfo,
|
|
|
|
lastError: retryRecord?.lastError,
|
2020-03-11 20:14:28 +01:00
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2021-06-25 13:27:06 +02:00
|
|
|
async function gatherBackupPending(
|
|
|
|
tx: GetReadOnlyAccess<{
|
|
|
|
backupProviders: typeof WalletStoresV1.backupProviders;
|
2022-09-05 18:12:30 +02:00
|
|
|
operationRetries: typeof WalletStoresV1.operationRetries;
|
2021-06-25 13:27:06 +02:00
|
|
|
}>,
|
2022-03-18 15:32:41 +01:00
|
|
|
now: AbsoluteTime,
|
2021-01-18 23:35:41 +01:00
|
|
|
resp: PendingOperationsResponse,
|
|
|
|
): Promise<void> {
|
2022-09-05 18:12:30 +02:00
|
|
|
await tx.backupProviders.iter().forEachAsync(async (bp) => {
|
|
|
|
const opId = RetryTags.forBackup(bp);
|
|
|
|
const retryRecord = await tx.operationRetries.get(opId);
|
2021-06-25 13:27:06 +02:00
|
|
|
if (bp.state.tag === BackupProviderStateTag.Ready) {
|
|
|
|
resp.pendingOperations.push({
|
|
|
|
type: PendingTaskType.Backup,
|
2022-09-05 18:12:30 +02:00
|
|
|
id: opId,
|
2021-06-25 13:27:06 +02:00
|
|
|
givesLifeness: false,
|
2022-03-18 15:32:41 +01:00
|
|
|
timestampDue: AbsoluteTime.fromTimestamp(bp.state.nextBackupTimestamp),
|
2021-06-25 13:27:06 +02:00
|
|
|
backupProviderBaseUrl: bp.baseUrl,
|
|
|
|
lastError: undefined,
|
|
|
|
});
|
|
|
|
} else if (bp.state.tag === BackupProviderStateTag.Retrying) {
|
|
|
|
resp.pendingOperations.push({
|
|
|
|
type: PendingTaskType.Backup,
|
2022-09-05 18:12:30 +02:00
|
|
|
id: opId,
|
2021-06-25 13:27:06 +02:00
|
|
|
givesLifeness: false,
|
2022-09-05 18:12:30 +02:00
|
|
|
timestampDue: retryRecord?.retryInfo?.nextRetry ?? AbsoluteTime.now(),
|
2021-06-25 13:27:06 +02:00
|
|
|
backupProviderBaseUrl: bp.baseUrl,
|
2022-09-05 18:12:30 +02:00
|
|
|
retryInfo: retryRecord?.retryInfo,
|
|
|
|
lastError: retryRecord?.lastError,
|
2021-06-25 13:27:06 +02:00
|
|
|
});
|
2021-01-18 23:35:41 +01:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2019-12-02 00:42:40 +01:00
|
|
|
export async function getPendingOperations(
|
|
|
|
ws: InternalWalletState,
|
|
|
|
): Promise<PendingOperationsResponse> {
|
2022-03-18 15:32:41 +01:00
|
|
|
const now = AbsoluteTime.now();
|
2021-06-09 15:26:18 +02:00
|
|
|
return await ws.db
|
2022-09-13 13:25:41 +02:00
|
|
|
.mktx((x) => [
|
|
|
|
x.backupProviders,
|
|
|
|
x.exchanges,
|
|
|
|
x.exchangeDetails,
|
|
|
|
x.refreshGroups,
|
|
|
|
x.coins,
|
|
|
|
x.withdrawalGroups,
|
|
|
|
x.proposals,
|
|
|
|
x.tips,
|
|
|
|
x.purchases,
|
|
|
|
x.planchets,
|
|
|
|
x.depositGroups,
|
|
|
|
x.recoupGroups,
|
|
|
|
x.operationRetries,
|
|
|
|
])
|
2021-06-09 15:26:18 +02:00
|
|
|
.runReadWrite(async (tx) => {
|
2020-03-06 15:09:55 +01:00
|
|
|
const resp: PendingOperationsResponse = {
|
|
|
|
pendingOperations: [],
|
|
|
|
};
|
2021-06-10 16:32:37 +02:00
|
|
|
await gatherExchangePending(tx, now, resp);
|
|
|
|
await gatherRefreshPending(tx, now, resp);
|
|
|
|
await gatherWithdrawalPending(tx, now, resp);
|
|
|
|
await gatherProposalPending(tx, now, resp);
|
2021-08-07 17:59:06 +02:00
|
|
|
await gatherDepositPending(tx, now, resp);
|
2021-06-10 16:32:37 +02:00
|
|
|
await gatherTipPending(tx, now, resp);
|
|
|
|
await gatherPurchasePending(tx, now, resp);
|
|
|
|
await gatherRecoupPending(tx, now, resp);
|
2021-06-25 13:27:06 +02:00
|
|
|
await gatherBackupPending(tx, now, resp);
|
2020-03-06 15:09:55 +01:00
|
|
|
return resp;
|
2021-06-09 15:26:18 +02:00
|
|
|
});
|
2019-12-02 00:42:40 +01:00
|
|
|
}
|