import { generateUuidV4FromUrl } from "#Source/identifier/index.ts" import type { LoggerFriendly, LoggerFriendlyOptions } from "#Source/log/index.ts" import { Logger } from "#Source/log/index.ts" import type { BaseSelector } from "./selector/index.ts" import { DownCountSelector } from "./selector/index.ts" interface ItemStates { item: Target available: boolean } export interface GetSelectorOptions { id?: string | undefined filter?: ((item: Target) => boolean) | undefined } export interface GetSelectorResult { selector: BaseSelector destroy: () => void } export interface DispatcherOptions extends LoggerFriendlyOptions { itemList: Target[] } export class Dispatcher implements LoggerFriendly { readonly logger: Logger private itemStatesMap: Map> private selectorMap: Map> constructor(options: DispatcherOptions) { this.logger = Logger.fromOptions(options).setDefaultName("Dispatcher") this.itemStatesMap = new Map() options.itemList.forEach((item) => { this.itemStatesMap.set(item, { item, available: true, }) }) this.selectorMap = new Map() } getSelector(options: GetSelectorOptions): GetSelectorResult { const { id = generateUuidV4FromUrl(), filter = (): boolean => true } = options const isInitialized = this.selectorMap.has(id) if (isInitialized === false) { const list = Array.from(this.itemStatesMap.values()) .filter((itemStates) => { return itemStates.available === true && filter(itemStates.item) === true }) .map((itemStates) => { return itemStates.item }) // TODO: 将 selector 的类型作为参数,从而实现不同的 dispatcher 策略 const selector = new DownCountSelector({ id, itemList: list, logger: this.logger.derive().setName(`Selector-${id}`), }) this.selectorMap.set(id, selector) } const selector = this.selectorMap.get(id)! const result = { selector, destroy: (): void => { this.destroySelector(id) }, } return result } destroySelector(key: string): void { this.selectorMap.delete(key) } }