mirror of
https://github.com/the-draupnir-project/Draupnir.git
synced 2026-10-23 01:21:16 +00:00
Split the Projection interface into distinct reader / writer sides.
https://github.com/the-draupnir-project/planning/issues/150
This commit is contained in:
4 files changed
+30
-7
No files matched your search
@@ -17,6 +17,8 @@ import {
|
||||
ProjectionNode,
|
||||
} from "./ProjectionNode";
|
||||
|
||||
export const ProjectionOrchestrationKey = Symbol("ProjectionOrchestration");
|
||||
|
||||
export type ProjectionNodeListener<
|
||||
TProjectionNode extends ProjectionNode = ProjectionNode,
|
||||
> = (
|
||||
@@ -25,10 +27,9 @@ export type ProjectionNodeListener<
|
||||
previousNode: TProjectionNode
|
||||
) => void;
|
||||
|
||||
export interface Projection<
|
||||
export interface ProjectionOrchestration<
|
||||
TProjectionNode extends AnyProjectionNode = AnyProjectionNode,
|
||||
> {
|
||||
readonly currentNode: TProjectionNode;
|
||||
addOutput(projection: Projection): this;
|
||||
removeOutput(projection: Projection): this;
|
||||
applyInput(input: ExtractProjectionInputs<TProjectionNode>): void;
|
||||
@@ -36,6 +37,13 @@ export interface Projection<
|
||||
removeNodeListener(listener: ProjectionNodeListener<TProjectionNode>): this;
|
||||
}
|
||||
|
||||
export interface Projection<
|
||||
TProjectionNode extends AnyProjectionNode = AnyProjectionNode,
|
||||
> {
|
||||
readonly currentNode: TProjectionNode;
|
||||
readonly [ProjectionOrchestrationKey]: ProjectionOrchestration<TProjectionNode>;
|
||||
}
|
||||
|
||||
export type ExtractProjectionNode<TProjection> =
|
||||
TProjection extends Projection<infer TProjectionNode>
|
||||
? TProjectionNode
|
||||
@@ -57,7 +65,7 @@ export type ExtractProjectionNode<TProjection> =
|
||||
export class ProjectionOutputHelper<
|
||||
TProjectionNode extends ProjectionNode = ProjectionNode,
|
||||
> {
|
||||
private readonly outputs = new Set<Projection<ProjectionNode>>();
|
||||
private readonly outputs = new Set<ProjectionOrchestration<ProjectionNode>>();
|
||||
private readonly emitter = new EventEmitter();
|
||||
public constructor(public currentNode: TProjectionNode) {
|
||||
// nothing to do.
|
||||
@@ -81,12 +89,12 @@ export class ProjectionOutputHelper<
|
||||
}
|
||||
|
||||
addOutput(projection: Projection): this {
|
||||
this.outputs.add(projection);
|
||||
this.outputs.add(projection[ProjectionOrchestrationKey]);
|
||||
return this;
|
||||
}
|
||||
|
||||
removeOutput(projection: Projection): this {
|
||||
this.outputs.delete(projection);
|
||||
this.outputs.delete(projection[ProjectionOrchestrationKey]);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ import { ProtectedRoomsSet } from "./ProtectedRoomsSet";
|
||||
import { Protection, ProtectionDescription } from "./Protection";
|
||||
import { AnyProjectionNode } from "../Projection/ProjectionNode";
|
||||
import { StandardHandleRegistryDescription } from "./HandleRegistry/StandardHandleRegistryDescription";
|
||||
import { ProjectionOrchestrationKey } from "../Projection/Projection";
|
||||
|
||||
export const ProtectionIntentProjectionNodeHandle: HandleDescription<
|
||||
"handleIntentProjectionNode",
|
||||
@@ -38,11 +39,15 @@ export const ProtectionIntentProjectionNodeHandle: HandleDescription<
|
||||
protection.handleIntentProjectionNode?.(node, delta);
|
||||
return lifetime.allocateResource(
|
||||
() => {
|
||||
protection.intentProjection?.addNodeListener(listener);
|
||||
protection.intentProjection?.[
|
||||
ProjectionOrchestrationKey
|
||||
].addNodeListener(listener);
|
||||
return Ok(listener);
|
||||
},
|
||||
() => () => {
|
||||
protection.intentProjection?.removeNodeListener(listener);
|
||||
protection.intentProjection?.[
|
||||
ProjectionOrchestrationKey
|
||||
].removeNodeListener(listener);
|
||||
}
|
||||
) as Result<void>;
|
||||
},
|
||||
|
||||
+5
@@ -14,6 +14,7 @@ import {
|
||||
} from "../../../MembershipPolicies/SetMembershipPolicyRevisionIssuer";
|
||||
import {
|
||||
Projection,
|
||||
ProjectionOrchestrationKey,
|
||||
ProjectionOutputHelper,
|
||||
} from "../../../Projection/Projection";
|
||||
import {
|
||||
@@ -44,6 +45,10 @@ export class StandardMemberBanIntentProjection
|
||||
);
|
||||
}
|
||||
|
||||
public get [ProjectionOrchestrationKey]() {
|
||||
return this;
|
||||
}
|
||||
|
||||
private handleUpstreamRevision = ((_revision, delta) => {
|
||||
this.applyInput(delta);
|
||||
}) satisfies SetMembershipPolicyRevisionListener;
|
||||
|
||||
+5
@@ -14,6 +14,7 @@ import {
|
||||
} from "../../../PolicyList/PolicyListRevisionIssuer";
|
||||
import {
|
||||
Projection,
|
||||
ProjectionOrchestrationKey,
|
||||
ProjectionOutputHelper,
|
||||
} from "../../../Projection/Projection";
|
||||
import {
|
||||
@@ -49,4 +50,8 @@ export class StandardServerBanIntentProjection
|
||||
this.policyListRevisionIssuer.off("revision", this.handleUpstreamRevision);
|
||||
super[Symbol.dispose]();
|
||||
}
|
||||
|
||||
public get [ProjectionOrchestrationKey]() {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user