1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-09-10 17:53:36 +02:00

fix: tear down also event handlers in addon service

This commit is contained in:
sjaanus 2025-07-03 11:17:51 +03:00
parent 2abbf976fe
commit bfbdc1f65a
No known key found for this signature in database
GPG Key ID: 20E007C0248BA7FF
2 changed files with 70 additions and 31 deletions

View File

@ -110,6 +110,13 @@ export default class EventService {
return this.eventStore.on(eventName, listener); return this.eventStore.on(eventName, listener);
} }
off(
eventName: string | symbol,
listener: (...args: any[]) => void,
): EventEmitter {
return this.eventStore.off(eventName, listener);
}
private async enhanceEventsWithTags( private async enhanceEventsWithTags(
events: IBaseEvent[], events: IBaseEvent[],
): Promise<IBaseEvent[]> { ): Promise<IBaseEvent[]> {

View File

@ -59,6 +59,8 @@ export default class AddonService {
fetchAddonConfigs: (() => Promise<IAddon[]>) & fetchAddonConfigs: (() => Promise<IAddon[]>) &
memoizee.Memoized<() => Promise<IAddon[]>>; memoizee.Memoized<() => Promise<IAddon[]>>;
private eventHandlers: Map<string, (event: IEvent) => void>;
constructor( constructor(
{ {
addonStore, addonStore,
@ -83,6 +85,7 @@ export default class AddonService {
this.logger = getLogger('services/addon-service.js'); this.logger = getLogger('services/addon-service.js');
this.tagTypeService = tagTypeService; this.tagTypeService = tagTypeService;
this.eventService = eventService; this.eventService = eventService;
this.eventHandlers = new Map();
this.addonProviders = this.addonProviders =
addons || addons ||
@ -124,15 +127,18 @@ export default class AddonService {
} }
registerEventHandler(): void { registerEventHandler(): void {
SUPPORTED_EVENTS.forEach((eventName) => SUPPORTED_EVENTS.forEach((eventName) => {
this.eventService.onEvent(eventName, this.handleEvent(eventName)), const handler = this.handleEvent(eventName);
); this.eventHandlers.set(eventName, handler);
this.eventService.onEvent(eventName, handler);
});
} }
handleEvent(eventName: string): (event: IEvent) => void { handleEvent(eventName: string): (event: IEvent) => void {
const { addonProviders } = this; const { addonProviders } = this;
return (event) => { return (event) => {
this.fetchAddonConfigs().then((addonInstances) => { this.fetchAddonConfigs()
.then((addonInstances) => {
addonInstances addonInstances
.filter((addon) => addon.events.includes(eventName)) .filter((addon) => addon.events.includes(eventName))
.filter( .filter(
@ -159,6 +165,18 @@ export default class AddonService {
addon.id, addon.id,
), ),
); );
})
.catch((error) => {
if (error.message === 'aborted') {
this.logger.debug(
`Addon event handling aborted during shutdown for event ${eventName}`,
);
} else {
this.logger.warn(
`Failed to handle addon event ${eventName}:`,
error,
);
}
}); });
}; };
} }
@ -349,6 +367,20 @@ export default class AddonService {
} }
destroy(): void { destroy(): void {
// Clean up event handlers first to prevent race conditions during teardown
this.eventHandlers.forEach((handler, eventName) => {
try {
this.eventService.off(eventName, handler);
} catch (error) {
this.logger.debug(
`Failed to remove event handler for ${eventName}:`,
error,
);
}
});
this.eventHandlers.clear();
// Then destroy addon providers
Object.values(this.addonProviders).forEach((addon) => Object.values(this.addonProviders).forEach((addon) =>
addon.destroy?.(), addon.destroy?.(),
); );