aboutsummaryrefslogtreecommitdiff
path: root/packages/taler-wallet-core
diff options
context:
space:
mode:
Diffstat (limited to 'packages/taler-wallet-core')
-rw-r--r--packages/taler-wallet-core/src/db.ts2
-rw-r--r--packages/taler-wallet-core/src/exchanges.ts27
-rw-r--r--packages/taler-wallet-core/src/shepherd.ts16
3 files changed, 39 insertions, 6 deletions
diff --git a/packages/taler-wallet-core/src/db.ts b/packages/taler-wallet-core/src/db.ts
index 07caa630b..7c2380e2d 100644
--- a/packages/taler-wallet-core/src/db.ts
+++ b/packages/taler-wallet-core/src/db.ts
@@ -677,6 +677,8 @@ export interface ExchangeEntryRecord {
updateStatus: ExchangeEntryDbUpdateStatus;
+ unavailableReason?: TalerErrorDetail;
+
/**
* If set to true, the next update to the exchange
* status will request /keys with no-cache headers set.
diff --git a/packages/taler-wallet-core/src/exchanges.ts b/packages/taler-wallet-core/src/exchanges.ts
index 903f79dcd..3bec30587 100644
--- a/packages/taler-wallet-core/src/exchanges.ts
+++ b/packages/taler-wallet-core/src/exchanges.ts
@@ -45,6 +45,7 @@ import {
ExchangeListItem,
ExchangeSignKeyJson,
ExchangeTosStatus,
+ ExchangeUpdateStatus,
ExchangeWireAccount,
ExchangesListResponse,
FeeDescription,
@@ -87,6 +88,7 @@ import {
hashDenomPub,
j2s,
makeErrorDetail,
+ makeTalerErrorDetail,
parsePaytoUri,
} from "@gnu-taler/taler-util";
import {
@@ -325,7 +327,7 @@ async function makeExchangeListItem(
scopeInfo = await internalGetExchangeScopeInfo(tx, exchangeDetails);
}
- return {
+ const listItem: ExchangeListItem = {
exchangeBaseUrl: r.baseUrl,
masterPub: exchangeDetails?.masterPublicKey,
noFees: r.noFees ?? false,
@@ -346,6 +348,14 @@ async function makeExchangeListItem(
url: r.baseUrl,
},
};
+ switch (listItem.exchangeUpdateStatus) {
+ case ExchangeUpdateStatus.UnavailableUpdate:
+ if (r.unavailableReason) {
+ listItem.unavailableReason = r.unavailableReason;
+ }
+ break;
+ }
+ return listItem;
}
export interface ExchangeWireDetails {
@@ -1476,16 +1486,18 @@ export async function updateExchangeFromUrlHandler(
detailsPointerChanged = true;
}
let detailsIncompatible = false;
+ let conflictHint: string | undefined = undefined;
if (existingDetails) {
if (existingDetails.masterPublicKey !== keysInfo.masterPublicKey) {
detailsIncompatible = true;
detailsPointerChanged = true;
- }
- if (existingDetails.currency !== keysInfo.currency) {
+ conflictHint = "master public key changed";
+ } else if (existingDetails.currency !== keysInfo.currency) {
detailsIncompatible = true;
detailsPointerChanged = true;
+ conflictHint = "currency changed";
}
- // FIXME: We need to do some consistency checks!
+ // FIXME: We need to do some more consistency checks!
}
if (detailsIncompatible) {
logger.warn(
@@ -1494,6 +1506,12 @@ export async function updateExchangeFromUrlHandler(
// We don't support this gracefully right now.
// See https://bugs.taler.net/n/8576
r.updateStatus = ExchangeEntryDbUpdateStatus.UnavailableUpdate;
+ r.unavailableReason = makeTalerErrorDetail(
+ TalerErrorCode.WALLET_EXCHANGE_ENTRY_UPDATE_CONFLICT,
+ {
+ detail: conflictHint,
+ },
+ );
r.updateRetryCounter = (r.updateRetryCounter ?? 0) + 1;
r.nextUpdateStamp = computeDbBackoff(r.updateRetryCounter);
r.nextRefreshCheckStamp = timestampPreciseToDb(
@@ -1506,6 +1524,7 @@ export async function updateExchangeFromUrlHandler(
newExchangeState: getExchangeState(r),
};
}
+ delete r.unavailableReason;
r.updateRetryCounter = 0;
const newDetails: ExchangeDetailsRecord = {
auditors: keysInfo.auditors,
diff --git a/packages/taler-wallet-core/src/shepherd.ts b/packages/taler-wallet-core/src/shepherd.ts
index 470f45aff..2b529fb4b 100644
--- a/packages/taler-wallet-core/src/shepherd.ts
+++ b/packages/taler-wallet-core/src/shepherd.ts
@@ -145,6 +145,14 @@ function taskGivesLiveness(taskId: string): boolean {
}
export interface TaskScheduler {
+ /**
+ * Ensure that the task scheduler is running.
+ *
+ * If it is not running, start it, with previous
+ * tasks loaded from the database.
+ *
+ * Returns after the scheduler is running.
+ */
ensureRunning(): Promise<void>;
startShepherdTask(taskId: TaskIdStr): void;
stopShepherdTask(taskId: TaskIdStr): void;
@@ -188,6 +196,9 @@ export class TaskSchedulerImpl implements TaskScheduler {
}
}
+ /**
+ * @see TaskScheduler.ensureRunning
+ */
async ensureRunning(): Promise<void> {
if (this.isRunning) {
return;
@@ -261,7 +272,7 @@ export class TaskSchedulerImpl implements TaskScheduler {
const tasksIds = [...this.sheps.keys()];
logger.info(`reloading shepherd with ${tasksIds.length} tasks`);
for (const taskId of tasksIds) {
- await this.stopShepherdTask(taskId);
+ this.stopShepherdTask(taskId);
}
for (const taskId of tasksIds) {
this.startShepherdTask(taskId);
@@ -276,9 +287,10 @@ export class TaskSchedulerImpl implements TaskScheduler {
return;
}
logger.trace(
- `Waiting old task to complete the loop in cancel mode ${taskId}`,
+ `Waiting for old task to complete the loop in cancel mode ${taskId}`,
);
await oldShep.latch;
+ logger.trace(`Old task ${taskId} completed in cancel mode`);
}
logger.trace(`Creating new shepherd for ${taskId}`);
const newShep: ShepherdInfo = {