diff --git a/src/dbos-executor.ts b/src/dbos-executor.ts index 2a63238cd..5a528b21a 100644 --- a/src/dbos-executor.ts +++ b/src/dbos-executor.ts @@ -675,8 +675,9 @@ export class DBOSExecutor implements DBOSExecutorContext { wCtxt.span.setStatus({ code: SpanStatusCode.OK }); } else { // Record the error. - const e: Error = err as Error; + const e = err as Error & {dbos_already_logged?: boolean}; this.logger.error(e); + e.dbos_already_logged = true if (wCtxt.isTempWorkflow) { internalStatus.name = `${DBOSExecutor.tempWorkflowName}-${wCtxt.tempWfOperationType}-${wCtxt.tempWfOperationName}`; } diff --git a/src/httpServer/server.ts b/src/httpServer/server.ts index de858bb13..3e53587b7 100644 --- a/src/httpServer/server.ts +++ b/src/httpServer/server.ts @@ -311,7 +311,10 @@ async checkPortAvailability(port: number, host: string): Promise { oc.span.setStatus({ code: SpanStatusCode.OK }); } catch (e) { if (e instanceof Error) { - oc.logger.error(e); + const annotated_e = e as Error & {dbos_already_logged?: boolean}; + if (annotated_e.dbos_already_logged !== true) { + oc.logger.error(e); + } oc.span.setStatus({ code: SpanStatusCode.ERROR, message: e.message }); let st = (e as DBOSResponseError)?.status || 500; const dbosErrorCode = (e as DBOSError)?.dbosErrorCode; diff --git a/src/scheduler/scheduler.ts b/src/scheduler/scheduler.ts index 86bb02c12..8d7746cda 100644 --- a/src/scheduler/scheduler.ts +++ b/src/scheduler/scheduler.ts @@ -15,7 +15,7 @@ export enum SchedulerMode { export class SchedulerConfig { crontab: string = '* * * * *'; // Every minute - mode ?: SchedulerMode = SchedulerMode.ExactlyOncePerInterval; + mode ?: SchedulerMode = SchedulerMode.ExactlyOncePerIntervalWhenActive; } //// diff --git a/src/workflow.ts b/src/workflow.ts index c4e93a04b..aef1228b8 100644 --- a/src/workflow.ts +++ b/src/workflow.ts @@ -781,7 +781,8 @@ export class WorkflowContextImpl extends DBOSContextImpl implements WorkflowCont try { result = await commFn.call(clsInst, ctxt, ...args); } catch (error) { - this.logger.error(error); + const e = error as Error + this.logger.warn(`Communicator error being automatically retried. Attempt ${numAttempts} of ${ctxt.maxAttempts}. ${e.stack}`); span.addEvent(`Communicator attempt ${numAttempts + 1} failed`, { "retryIntervalSeconds": intervalSeconds, "error": (error as Error).message }, performance.now()); if (numAttempts < ctxt.maxAttempts) { // Sleep for an interval, then increase the interval by backoffRate. diff --git a/tests/failures.test.ts b/tests/failures.test.ts index ad1425121..e8efcd598 100644 --- a/tests/failures.test.ts +++ b/tests/failures.test.ts @@ -179,7 +179,7 @@ class FailureTestClass { return await ctxt.invoke(FailureTestClass).testSerialError(maxRetry); } - @Communicator({ intervalSeconds: 1, maxAttempts: 2 }) + @Communicator({ retriesAllowed: true, intervalSeconds: 1, maxAttempts: 2 }) static async testFailCommunicator(ctxt: CommunicatorContext) { FailureTestClass.cnt++; if (ctxt.retriesAllowed && FailureTestClass.cnt !== ctxt.maxAttempts) {