1/**
2 * The `EntityAddress` module defines the value used to locate an entity within
3 * a cluster. An address combines the entity type, entity id, and shard id so
4 * messages, persisted envelopes, workflow executions, and entity managers can
5 * agree on the same routing target.
6 *
7 * @stability unstable
8 * @since 4.0.0
9 */
10import * as Equal from "../Equal.ts"
11import * as Hash from "../Hash.ts"
12import * as Schema from "../Schema.ts"
13import { EntityId } from "./EntityId.ts"
14import { EntityType } from "./EntityType.ts"
15import { ShardId } from "./ShardId.ts"
16
17const TypeId = "~effect/cluster/EntityAddress"
18
19/**
20 * Represents the unique address of an entity within the cluster.
21 *
22 * @stability unstable
23 * @category models
24 * @since 4.0.0
25 */
26export class EntityAddress extends Schema.Class<EntityAddress>(TypeId)({
27 shardId: ShardId,
28 entityType: EntityType,
29 entityId: EntityId
30}) {
31 /**
32 * Marks this value as a cluster entity address for runtime guards.
33 *
34 * @stability unstable
35 * @since 4.0.0
36 */
37 readonly [TypeId] = TypeId
38
39 /**
40 * Formats the entity type, entity id, and shard id as a readable address.
41 *
42 * @stability unstable
43 * @since 4.0.0
44 */
45 override toString() {
46 return `EntityAddress(${this.entityType.toString()}, ${this.entityId.toString()}, ${this.shardId.toString()})`
47 }
48
49 /**
50 * Compares entity addresses by entity type, entity id, and shard id.
51 *
52 * @stability unstable
53 * @since 4.0.0
54 */
55 [Equal.symbol](that: EntityAddress): boolean {
56 return this.entityType === that.entityType && this.entityId === that.entityId &&
57 Equal.equals(this.shardId, that.shardId)
58 }
59
60 /**
61 * Computes a structural hash from the entity type, entity id, and shard id.
62 *
63 * @stability unstable
64 * @since 4.0.0
65 */
66 [Hash.symbol]() {
67 return Hash.string(`${this.entityType}:${this.entityId}:${this.shardId.toString()}`)
68 }
69}
70/**
71 * Constructs an `EntityAddress` from a shard ID, entity type, and entity ID.
72 *
73 * **When to use**
74 *
75 * Use to create the routing target for a known entity type and entity id after
76 * resolving that id to the `ShardId` assigned by the entity's shard group.
77 *
78 * **Details**
79 *
80 * The returned `EntityAddress` stores the supplied `shardId`, `entityType`, and
81 * `entityId`. Equality and hashing include all three fields.
82 *
83 * **Gotchas**
84 *
85 * `make` does not choose the shard for an entity. Use the same shard group
86 * logic as the entity definition; a different `shardId` makes a different
87 * address even when the entity type and entity id match.
88 *
89 * @see {@link EntityAddress} for the equality, hashing, and string formatting behavior of constructed addresses
90 * @see {@link ShardId} for the shard identifier included in the address
91 *
92 * @stability unstable
93 * @category constructors
94 * @since 4.0.0
95 */
96export const make = (options: {
97 readonly shardId: ShardId
98 readonly entityType: EntityType
99 readonly entityId: EntityId
100}): EntityAddress => new EntityAddress(options, { disableChecks: true })