Skip to content

Commit 8c0bff5

Browse files
authored
feat: Use .reboot() instead of .metamorph() for reboot (#227)
1 parent 6adaeed commit 8c0bff5

File tree

4 files changed

+35
-30
lines changed

4 files changed

+35
-30
lines changed

Diff for: package-lock.json

+8-8
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: packages/apify/package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,10 @@
6262
"@crawlee/core": "^3.5.3",
6363
"@crawlee/types": "^3.5.3",
6464
"@crawlee/utils": "^3.5.3",
65-
"apify-client": "^2.7.1",
65+
"apify-client": "^2.8.0",
6666
"ow": "^0.28.2",
6767
"semver": "^7.5.4",
6868
"tslib": "^2.6.0",
6969
"ws": "^7.5.9"
7070
}
71-
}
71+
}

Diff for: packages/apify/src/actor.ts

+15-6
Original file line numberDiff line numberDiff line change
@@ -441,22 +441,26 @@ export class Actor<Data extends Dictionary = Dictionary> {
441441
*
442442
* @ignore
443443
*/
444-
async reboot(): Promise<void> {
444+
async reboot(options: RebootOptions = {}): Promise<void> {
445445
if (!this.isAtHome()) {
446446
log.warning('Actor.reboot() is only supported when running on the Apify platform.');
447447
return;
448448
}
449449

450-
// Waiting for all the listeners to finish, as `.metamorph()` kills the container.
450+
// Waiting for all the listeners to finish, as `.reboot()` kills the container.
451451
await Promise.all([
452452
// `persistState` for individual RequestLists, RequestQueue... instances to be persisted
453453
...this.config.getEventManager().listeners(EventType.PERSIST_STATE).map((x) => x()),
454454
// `migrating` to pause Apify crawlers
455455
...this.config.getEventManager().listeners(EventType.MIGRATING).map((x) => x()),
456456
]);
457457

458-
const actorId = this.config.get('actorId')!;
459-
await this.metamorph(actorId);
458+
const runId = this.config.get('actorRunId')!;
459+
await this.apifyClient.run(runId).reboot();
460+
461+
// Wait some time for container to be stopped.
462+
const { customAfterSleepMillis = this.config.get('metamorphAfterSleepMillis') } = options;
463+
await sleep(customAfterSleepMillis);
460464
}
461465

462466
/**
@@ -1177,8 +1181,8 @@ export class Actor<Data extends Dictionary = Dictionary> {
11771181
* Internally reboots this actor run. The system stops the current container and starts
11781182
* a new container with the same run id.
11791183
*/
1180-
static async reboot(): Promise<void> {
1181-
return Actor.getDefaultInstance().reboot();
1184+
static async reboot(options: RebootOptions = {}): Promise<void> {
1185+
return Actor.getDefaultInstance().reboot(options);
11821186
}
11831187

11841188
/**
@@ -1652,6 +1656,11 @@ export interface MetamorphOptions {
16521656
customAfterSleepMillis?: number;
16531657
}
16541658

1659+
export interface RebootOptions {
1660+
/** @internal */
1661+
customAfterSleepMillis?: number;
1662+
}
1663+
16551664
export interface ExitOptions {
16561665
/** Exit with given status message */
16571666
statusMessage?: string;

Diff for: test/apify/actor.test.ts

+10-14
Original file line numberDiff line numberDiff line change
@@ -830,6 +830,7 @@ describe('Actor', () => {
830830

831831
describe('Actor.reboot()', () => {
832832
const { actId, runId } = globalOptions;
833+
const { run } = runConfigs;
833834

834835
beforeEach(() => {
835836
process.env[APIFY_ENV_VARS.IS_AT_HOME] = '1';
@@ -844,19 +845,11 @@ describe('Actor', () => {
844845
jest.restoreAllMocks();
845846
});
846847

847-
test('metamorphs to the same actor', async () => {
848-
const metamorphSpy = jest.spyOn(Actor.prototype, 'metamorph');
849-
metamorphSpy.mockResolvedValueOnce();
850-
851-
await Actor.reboot();
852-
853-
expect(metamorphSpy).toBeCalledTimes(1);
854-
expect(metamorphSpy).toBeCalledWith(actId);
855-
});
856-
857-
test('reboot waits for persistState/migrating listeners before morphing', async () => {
858-
const metamorphSpy = jest.spyOn(Actor.prototype, 'metamorph');
859-
metamorphSpy.mockResolvedValueOnce();
848+
test('reboot waits for persistState/migrating listeners before rebooting', async () => {
849+
const rebootMock = jest.fn();
850+
rebootMock.mockResolvedValueOnce(run);
851+
const rebootSpy = jest.spyOn(ApifyClient.prototype, 'run');
852+
rebootSpy.mockReturnValueOnce({ reboot: rebootMock } as any);
860853

861854
const persistenceStore = [];
862855

@@ -872,7 +865,7 @@ describe('Actor', () => {
872865
events.on(EventType.PERSIST_STATE, persistStateSpy);
873866
events.on(EventType.MIGRATING, migratingSpy);
874867

875-
await Actor.reboot();
868+
await Actor.reboot({ customAfterSleepMillis: 1 });
876869

877870
events.off(EventType.PERSIST_STATE, persistStateSpy);
878871
events.off(EventType.MIGRATING, migratingSpy);
@@ -883,6 +876,9 @@ describe('Actor', () => {
883876

884877
// Do the listeners finish?
885878
expect(persistenceStore.length).toBe(2);
879+
880+
// Did the client's reboot method get called?
881+
expect(rebootMock).toBeCalledTimes(1);
886882
});
887883
});
888884

0 commit comments

Comments
 (0)