Skip to content

Commit

Permalink
Merge pull request #641 from golemfactory/feature/JST-535/increase-wa…
Browse files Browse the repository at this point in the history
…iting-for-offers-timeout

JST-535 | JST-536 customize the behavior of `startupTimeout` with `exitOnNoProposals` flag
  • Loading branch information
SewerynKras authored Nov 7, 2023
2 parents 552d481 + df87620 commit 2d598a3
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 11 deletions.
5 changes: 4 additions & 1 deletion src/executor/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ const DEFAULTS = Object.freeze({
taskTimeout: 1000 * 60 * 5, // 5 min,
maxTaskRetries: 3,
enableLogging: true,
startupTimeout: 1000 * 30, // 30 sec
startupTimeout: 1000 * 90, // 90 sec
exitOnNoProposals: false,
});

/**
Expand All @@ -36,6 +37,7 @@ export class ExecutorConfig {
readonly activityExecuteTimeout?: number;
readonly jobStorage: JobStorage;
readonly startupTimeout: number;
readonly exitOnNoProposals: boolean;

constructor(options: ExecutorOptions & ActivityOptions) {
const processEnv = !runtimeContextChecker.isBrowser
Expand Down Expand Up @@ -86,5 +88,6 @@ export class ExecutorConfig {
this.maxTaskRetries = options.maxTaskRetries ?? DEFAULTS.maxTaskRetries;
this.jobStorage = options.jobStorage || new InMemoryJobStorage();
this.startupTimeout = options.startupTimeout ?? DEFAULTS.startupTimeout;
this.exitOnNoProposals = options.exitOnNoProposals ?? DEFAULTS.exitOnNoProposals;
}
}
33 changes: 31 additions & 2 deletions src/executor/executor.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,14 @@ describe("Task Executor", () => {
expect(executor).toBeDefined();
await executor.end();
});
it("should handle a critical error if startup timeout is reached", async () => {
const executor = await TaskExecutor.create({ package: "test", startupTimeout: 0, logger, yagnaOptions });
it("should handle a critical error if startup timeout is reached and exitOnNoProposals is enabled", async () => {
const executor = await TaskExecutor.create({
package: "test",
startupTimeout: 0,
exitOnNoProposals: true,
logger,
yagnaOptions,
});
jest
.spyOn(MarketService.prototype, "getProposalsCount")
.mockImplementation(() => ({ confirmed: 0, initial: 0, rejected: 0 }));
Expand All @@ -62,6 +68,29 @@ describe("Task Executor", () => {
expect(handleErrorSpy).toHaveBeenCalled();
await executor.end();
});
it("should only warn the user if startup timeout is reached and exitOnNoProposals is disabled", async () => {
const executor = await TaskExecutor.create({
package: "test",
startupTimeout: 0,
exitOnNoProposals: false,
logger,
yagnaOptions,
});
jest
.spyOn(MarketService.prototype, "getProposalsCount")
.mockImplementation(() => ({ confirmed: 0, initial: 0, rejected: 0 }));
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const handleErrorSpy = jest.spyOn(executor as any, "handleCriticalError");
const loggerWarnSpy = jest.spyOn(logger, "warn");

await sleep(10, true);

expect(handleErrorSpy).not.toHaveBeenCalled();
expect(loggerWarnSpy).toHaveBeenCalledWith(
"Could not start any work on Golem. Processed 0 initial proposals from yagna, filters accepted 0. Check your demand if it's not too restrictive or restart yagna.",
);
await executor.end();
});
});

describe("end()", () => {
Expand Down
24 changes: 16 additions & 8 deletions src/executor/executor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,14 +64,21 @@ export type ExecutorOptions = {
*/
skipProcessSignals?: boolean;
/**
* Timeout for waiting for at least one offer from the market.
* This parameter (set to 30 sec by default) will throw an error when executing `TaskExecutor.run`
* if no offer from the market is accepted before this time.
* Timeout for waiting for at least one offer from the market expressed in milliseconds.
* This parameter (set to 90 sec by default) will issue a warning when executing `TaskExecutor.run`
* if no offer from the market is accepted before this time. If you'd like to change this behavior,
* and throw an error instead, set `exitOnNoProposals` to `true`.
* You can set a slightly higher time in a situation where your parameters such as proposalFilter
* or minimum hardware requirements are quite restrictive and finding a suitable provider
* that meets these criteria may take a bit longer.
*/
startupTimeout?: number;
/**
* If set to `true`, the executor will exit with an error when no proposals are accepted.
* You can customize how long the executor will wait for proposals using the `startupTimeout` parameter.
* Default is `false`.
*/
exitOnNoProposals?: boolean;
} & Omit<PackageOptions, "imageHash" | "imageTag"> &
MarketOptions &
TaskServiceOptions &
Expand Down Expand Up @@ -550,11 +557,12 @@ export class TaskExecutor {
: proposalsCount.initial === proposalsCount.rejected
? "All off proposals got rejected."
: "Check your proposal filters if they are not too restrictive.";
this.handleCriticalError(
new Error(
`Could not start any work on Golem. Processed ${proposalsCount.initial} initial proposals from yagna, filters accepted ${proposalsCount.confirmed}. ${hint}`,
),
);
const errorMessage = `Could not start any work on Golem. Processed ${proposalsCount.initial} initial proposals from yagna, filters accepted ${proposalsCount.confirmed}. ${hint}`;
if (this.options.exitOnNoProposals) {
this.handleCriticalError(new Error(errorMessage));
} else {
this.logger?.warn(errorMessage);
}
}
}, this.options.startupTimeout);
}
Expand Down

0 comments on commit 2d598a3

Please sign in to comment.