Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions code/core/src/manager-errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export enum Category {
MANAGER_CORE_EVENTS = 'MANAGER_CORE-EVENTS',
MANAGER_ROUTER = 'MANAGER_ROUTER',
MANAGER_THEMING = 'MANAGER_THEMING',
MANAGER_UNIVERSAL_STORE = 'MANAGER_UNIVERSAL-STORE',
}

export class ProviderDoesNotExtendBaseProviderError extends StorybookError {
Expand Down Expand Up @@ -66,3 +67,14 @@ export class StatusTypeIdMismatchError extends StorybookError {
});
}
}

export class UniversalStoreFollowerTimeoutError extends StorybookError {
constructor(followerId: string) {
super({
name: 'UniversalStoreFollowerTimeoutError',
category: Category.MANAGER_UNIVERSAL_STORE,
code: 1,
message: `Timed out waiting for leader state for UniversalStore follower with id: '${followerId}'. Ensure a leader with the same id exists and is reachable before creating a follower.`,
});
}
}
5 changes: 3 additions & 2 deletions code/core/src/shared/universal-store/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { UniversalStore } from './index.ts';
import { instances as mockedInstances } from './__mocks__/instances.ts';
import { MockUniversalStore } from './mock.ts';
import type { ChannelEvent } from './types.ts';
import { UniversalStoreFollowerTimeoutError } from '../../manager-errors.ts';

vi.mock('./instances');

Expand Down Expand Up @@ -690,8 +691,8 @@ You should reuse the existing instance instead of trying to create a new one.`);

// Assert - eventually the follower.untilReady() promise should throw an error when the timeout is reached
vi.advanceTimersToNextTimer();
await expect(follower.untilReady()).rejects.toThrowErrorMatchingInlineSnapshot(
`[TypeError: No existing state found for follower with id: 'env1:test'. Make sure a leader with the same id exists before creating a follower.]`
await expect(follower.untilReady()).rejects.toBeInstanceOf(
UniversalStoreFollowerTimeoutError
);
expect(follower.status).toBe(UniversalStore.Status.ERROR);
});
Expand Down
9 changes: 2 additions & 7 deletions code/core/src/shared/universal-store/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import type {
StatusType,
StoreOptions,
} from './types.ts';
import { UniversalStoreFollowerTimeoutError } from '../../manager-errors.ts';

const CHANNEL_EVENT_PREFIX = 'UNIVERSAL_STORE:' as const;

Expand Down Expand Up @@ -542,13 +543,7 @@ export class UniversalStore<
);
// 2. Wait 1 sec for a response, then reject the syncing promise if not already resolved
setTimeout(() => {
// if the state is already resolved by a response before this timeout,
// rejecting it doesn't do anything, it will be ignored
this.syncing!.reject!(
new TypeError(
`No existing state found for follower with id: '${this.id}'. Make sure a leader with the same id exists before creating a follower.`
)
);
this.syncing!.reject!(new UniversalStoreFollowerTimeoutError(this.id));
}, 1000);
}
}
Expand Down
Loading