Skip to content

Commit

Permalink
[core] Inspect subscription (#4936)
Browse files Browse the repository at this point in the history
* Make actor.system.inspect return a subscription

* Changeset
  • Loading branch information
davidkpiano authored Jun 18, 2024
1 parent 28d437c commit c58b36d
Show file tree
Hide file tree
Showing 3 changed files with 131 additions and 3 deletions.
24 changes: 24 additions & 0 deletions .changeset/cold-planes-clap.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
---
'xstate': minor
---

Inspecting an actor system via `actor.system.inspect(ev => …)` now accepts a function or observer, and returns a subscription:

```ts
const actor = createActor(someMachine);

const sub = actor.system.inspect((inspectionEvent) => {
console.log(inspectionEvent);
});

// Inspection events will be logged
actor.start();
actor.send({ type: 'anEvent' });

// ...

sub.unsubscribe();

// Will no longer log inspection events
actor.send({ type: 'someEvent' });
```
20 changes: 17 additions & 3 deletions packages/core/src/system.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ import {
Snapshot,
HomomorphicOmit,
EventObject,
AnyTransitionDefinition
AnyTransitionDefinition,
Subscription
} from './types.ts';
import { toObserver } from './utils.ts';

export interface ScheduledEvent {
id: string;
Expand Down Expand Up @@ -63,7 +65,12 @@ export interface ActorSystem<T extends ActorSystemInfo> {
*/
_set: <K extends keyof T['actors']>(key: K, actorRef: T['actors'][K]) => void;
get: <K extends keyof T['actors']>(key: K) => T['actors'][K] | undefined;
inspect: (observer: Observer<InspectionEvent>) => void;

inspect: (
observer:
| Observer<InspectionEvent>
| ((inspectionEvent: InspectionEvent) => void)
) => Subscription;
/**
* @internal
*/
Expand Down Expand Up @@ -206,8 +213,15 @@ export function createSystem<T extends ActorSystemInfo>(
keyedActors.set(systemId, actorRef);
reverseKeyedActors.set(actorRef, systemId);
},
inspect: (observer) => {
inspect: (observerOrFn) => {
const observer = toObserver(observerOrFn);
inspectionObservers.add(observer);

return {
unsubscribe() {
inspectionObservers.delete(observer);
}
};
},
_sendInspectionEvent: sendInspectionEvent as any,
_relay: (source, target, event) => {
Expand Down
90 changes: 90 additions & 0 deletions packages/core/test/inspect.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1032,4 +1032,94 @@ describe('inspect', () => {
actor.start();
actor.send({ type: 'any' });
});

it('actor.system.inspect(…) can inspect actors', () => {
const actor = createActor(createMachine({}));
const events: InspectionEvent[] = [];

actor.system.inspect((ev) => {
events.push(ev);
});

actor.start();

expect(events).toContainEqual(
expect.objectContaining({
type: '@xstate.event'
})
);
expect(events).toContainEqual(
expect.objectContaining({
type: '@xstate.snapshot'
})
);
});

it('actor.system.inspect(…) can inspect actors (observer)', () => {
const actor = createActor(createMachine({}));
const events: InspectionEvent[] = [];

actor.system.inspect({
next: (ev) => {
events.push(ev);
}
});

actor.start();

expect(events).toContainEqual(
expect.objectContaining({
type: '@xstate.event'
})
);
expect(events).toContainEqual(
expect.objectContaining({
type: '@xstate.snapshot'
})
);
});

it('actor.system.inspect(…) can be unsubscribed', () => {
const actor = createActor(createMachine({}));
const events: InspectionEvent[] = [];

const sub = actor.system.inspect((ev) => {
events.push(ev);
});

actor.start();

expect(events.length).toEqual(2);

events.length = 0;

sub.unsubscribe();

actor.send({ type: 'someEvent' });

expect(events.length).toEqual(0);
});

it('actor.system.inspect(…) can be unsubscribed (observer)', () => {
const actor = createActor(createMachine({}));
const events: InspectionEvent[] = [];

const sub = actor.system.inspect({
next: (ev) => {
events.push(ev);
}
});

actor.start();

expect(events.length).toEqual(2);

events.length = 0;

sub.unsubscribe();

actor.send({ type: 'someEvent' });

expect(events.length).toEqual(0);
});
});

0 comments on commit c58b36d

Please sign in to comment.