Skip to content

Commit

Permalink
max history & unregister reset
Browse files Browse the repository at this point in the history
  • Loading branch information
PS committed Nov 4, 2024
1 parent f6cc85c commit 8fa0ea7
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 23 deletions.
3 changes: 3 additions & 0 deletions packages/core/src/boot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,9 @@ export interface Settings {
$Page: {
$Render: PageRendererSettings;
};
$Observable?: {
maxHistoryLength: number;
};
}

/**
Expand Down
41 changes: 23 additions & 18 deletions packages/core/src/event/Observable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,28 @@ import {
DispatcherEventsMap,
DispatcherListener,
} from './Dispatcher';
import { Settings } from '../boot';
import { Dependencies } from '../oc/ObjectContainer';
import { RendererEvents } from '../page/renderer/RendererEvents';
import { RouterEvents } from '../router/RouterEvents';

export class Observable {
protected _dispatcher: Dispatcher;
protected _observers: Map<string, Map<DispatcherListener<any>, Set<unknown>>>;
protected _activityHistory: Map<string, unknown[]>;
protected _pageResetEvents: Set<string>;
protected _persistentEvents: Set<string>;
protected _settings: Settings['$Observable'];

static $dependencies: Dependencies = ['$Dispatcher'];
static $dependencies: Dependencies = [
'$Dispatcher',
'?$Settings.$Observable',
];

constructor(dispatcher: Dispatcher) {
constructor(dispatcher: Dispatcher, settings?: Settings['$Observable']) {
this._dispatcher = dispatcher;
this._observers = new Map();
this._activityHistory = new Map();
this._pageResetEvents = new Set();
this._persistentEvents = new Set();
this._settings = settings;

this.clear();
}
Expand All @@ -35,19 +40,11 @@ export class Observable {
clear() {
this._observers.clear();
this._activityHistory.clear();
this._pageResetEvents.clear();

Object.values(RouterEvents).forEach(event =>
this._pageResetEvents.add(event)
);

Object.values(RendererEvents).forEach(event =>
this._pageResetEvents.add(event)
);
this._persistentEvents.clear();
}

registerPageReset(event: keyof DispatcherEventsMap | string) {
this._pageResetEvents.add(event);
unregisterPageReset(event: keyof DispatcherEventsMap | string) {
this._persistentEvents.add(event);
}

subscribe(
Expand Down Expand Up @@ -98,8 +95,10 @@ export class Observable {

_handleDispatcherEvent(event: string, data: any) {
if (event === RouterEvents.BEFORE_HANDLE_ROUTE) {
for (const pageResetEvent of this._pageResetEvents) {
this._activityHistory.delete(pageResetEvent);
for (const [eventKey] of this._activityHistory) {
if (!this._persistentEvents.has(eventKey)) {
this._activityHistory.delete(eventKey);
}
}
}

Expand All @@ -108,6 +107,12 @@ export class Observable {
}

this._activityHistory.get(event)!.push(data);
this._activityHistory.set(
event,
this._activityHistory
.get(event)!
.splice(-(this._settings?.maxHistoryLength || 10))
);

if (!this._observers.has(event)) {
return;
Expand Down
30 changes: 26 additions & 4 deletions packages/core/src/event/__tests__/ObservableSpec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,22 @@ describe('ima.core.event.Observable', () => {
expect(observer).toHaveBeenLastCalledWith({ 3: 4 });
});

it('should subscribe to event and get data if already mrkev fired multiple times', () => {
const observable2 = new Observable(dispatcher, { maxHistoryLength: 2 });
observable2.init();

dispatcher.fire(event, eventData);
dispatcher.fire(event, { 1: 2 });
dispatcher.fire(event, { 3: 4 });

const observer = jest.fn();
observable2.subscribe(event, observer);

expect(observer).not.toHaveBeenCalledWith(eventData);
expect(observer).toHaveBeenCalledWith({ 1: 2 });
expect(observer).toHaveBeenLastCalledWith({ 3: 4 });
});

it('should work with scope', () => {
class Foo {
foo = jest.fn();
Expand Down Expand Up @@ -101,26 +117,32 @@ describe('ima.core.event.Observable', () => {

observer.mockClear();
observable.unsubscribe(event, observer);
dispatcher.fire(event, { foor: 'bar' });
dispatcher.fire(event, { foo: 'bar' });

expect(observer).not.toHaveBeenCalled();
expect(observable['_observers'].get(event)?.size).toBe(0);
});
});

it('should reset page events', () => {
observable.registerPageReset(event);
it('should reset only page events', () => {
observable.unregisterPageReset(event);
dispatcher.fire(event, eventData);
dispatcher.fire('foo', 'bar');
dispatcher.fire(RouterEvents.BEFORE_HANDLE_ROUTE, { bhr: true });

const eventObserver = jest.fn();
observable.subscribe(event, eventObserver);

expect(eventObserver).not.toHaveBeenCalledWith(eventData);
expect(eventObserver).toHaveBeenCalledWith(eventData);

const bhrObserver = jest.fn();
observable.subscribe(RouterEvents.BEFORE_HANDLE_ROUTE, bhrObserver);

expect(bhrObserver).toHaveBeenCalledWith({ bhr: true });

const fooObserver = jest.fn();
observable.subscribe('foo', fooObserver);

expect(fooObserver).not.toHaveBeenCalled();
});
});
1 change: 0 additions & 1 deletion packages/core/src/router/ServerRouter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ export class ServerRouter extends AbstractRouter {
Request,
Response,
'?$Settings.$Router.middlewareTimeout',
'?$Settings.$Router.isSPARouted',
];
}

Expand Down

0 comments on commit 8fa0ea7

Please sign in to comment.