1/**
2 * Cluster runner metadata for processes that can host entity shards.
3 *
4 * A `Runner` combines the stable `RunnerAddress` used to contact a process, the
5 * shard groups that process participates in, and the relative weight used when
6 * the sharding service distributes shards across healthy runners.
7 *
8 * @stability unstable
9 * @since 4.0.0
10 */
11import * as Equal from "../Equal.ts"
12import * as Hash from "../Hash.ts"
13import { NodeInspectSymbol } from "../Inspectable.ts"
14import * as Schema from "../Schema.ts"
15import { RunnerAddress } from "./RunnerAddress.ts"
16
17const TypeId = "~effect/cluster/Runner"
18
19/**
20 * Represents a cluster runner that can host entities.
21 *
22 * **Details**
23 *
24 * Each runner has a unique network `address`, the shard `groups` it participates
25 * in, and a relative `weight` used when assigning shards across runners.
26 *
27 * @stability unstable
28 * @category models
29 * @since 4.0.0
30 */
31export class Runner extends Schema.Class<Runner>(TypeId)({
32 address: RunnerAddress,
33 groups: Schema.Array(Schema.String),
34 weight: Schema.Finite
35}) {
36 /**
37 * Formatter for rendering runner values consistently.
38 *
39 * @stability unstable
40 * @since 4.0.0
41 */
42 static format = Schema.toFormatter(this)
43
44 /**
45 * Marks this value as a cluster runner for runtime guards.
46 *
47 * @stability unstable
48 * @since 4.0.0
49 */
50 readonly [TypeId] = TypeId
51
52 /**
53 * Decodes a runner from its JSON string representation.
54 *
55 * @stability unstable
56 * @since 4.0.0
57 */
58 static readonly decodeSync = Schema.decodeSync(Schema.fromJsonString(Runner))
59
60 /**
61 * Encodes a runner to its JSON string representation.
62 *
63 * @stability unstable
64 * @since 4.0.0
65 */
66 static readonly encodeSync = Schema.encodeSync(Schema.fromJsonString(Runner))
67
68 /**
69 * Formats this runner as a string.
70 *
71 * @stability unstable
72 * @since 4.0.0
73 */
74 override toString(): string {
75 return Runner.format(this)
76 }
77
78 /**
79 * Formats this runner for Node.js inspection.
80 *
81 * @stability unstable
82 * @since 4.0.0
83 */
84 [NodeInspectSymbol](): string {
85 return this.toString()
86 }
87
88 /**
89 * Compares runners by address and shard-assignment weight.
90 *
91 * @stability unstable
92 * @since 4.0.0
93 */
94 [Equal.symbol](that: Runner): boolean {
95 return this.address[Equal.symbol](that.address) && this.weight === that.weight
96 }
97
98 /**
99 * Computes a structural hash from the runner address and shard-assignment weight.
100 *
101 * @stability unstable
102 * @since 4.0.0
103 */
104 [Hash.symbol](): number {
105 return Hash.string(`${this.address.toString()}:${this.weight}`)
106 }
107}
108
109/**
110 * Constructs a `Runner` from its network address, shard groups, and relative
111 * shard-assignment weight.
112 *
113 * **When to use**
114 *
115 * Use to build runner metadata from an existing `RunnerAddress`, shard groups,
116 * and relative weight when registering or exchanging a cluster runner.
117 *
118 * **Details**
119 *
120 * The `groups` array lists the shard groups the runner can host. During shard
121 * assignment, the runner's address is added to each group's hash ring with
122 * `weight` as its relative weight.
123 *
124 * **Gotchas**
125 *
126 * This helper constructs the value without runtime schema validation, so only
127 * pass trusted `RunnerAddress`, `groups`, and `weight` values.
128 *
129 * @see {@link Runner} for the value created by this helper
130 * @see {@link RunnerAddress} for the network address accepted in `props.address`
131 *
132 * @stability unstable
133 * @category constructors
134 * @since 4.0.0
135 */
136export const make = (props: {
137 readonly address: RunnerAddress
138 readonly groups: ReadonlyArray<string>
139 readonly weight: number
140}): Runner => new Runner(props, { disableChecks: true })