|
1 | 1 | --- |
2 | 2 | title: Relocation |
3 | 3 | description: Automatic actor migration when nodes leave the cluster. |
4 | | -sidebarTitle: "Relocation" |
| 4 | +sidebarTitle: 'Relocation' |
5 | 5 | --- |
6 | 6 |
|
7 | 7 | **Relocation** is the automatic migration of actors and grains from a node that has left the cluster to the remaining |
8 | 8 | live nodes. Whether a node shuts down **gracefully** or **crashes**, its relocatable actors and grains are recreated on |
9 | 9 | other nodes so the cluster remains available. |
10 | 10 |
|
11 | 11 | <Note> |
12 | | - Relocation works for both graceful and abrupt departures. On a graceful shutdown the departing node replicates a |
13 | | - `PeerState` snapshot to its oldest peers. On a crash (`kill -9`, OOM, network partition) that snapshot never gets |
14 | | - written, so the leader instead reconstructs the departed node's relocation set from the replicated cluster registry. |
15 | | - Actors spawned with `WithRelocationDisabled` are still lost with the node either way. |
| 12 | + Relocation works for both graceful and abrupt departures. On a graceful shutdown the departing node replicates a `PeerState` snapshot to |
| 13 | + its oldest peers. On a crash (`kill -9`, OOM, network partition) that snapshot never gets written, so the leader instead reconstructs the |
| 14 | + departed node's relocation set from the replicated cluster registry. Actors spawned with `WithRelocationDisabled` are still lost with the |
| 15 | + node either way. |
16 | 16 | </Note> |
17 | 17 |
|
18 | 18 | ## When relocation happens |
@@ -113,9 +113,8 @@ Item failures are isolated: a failing actor, grain, or peer never aborts the res |
113 | 113 | self-heals when the grain is next addressed. |
114 | 114 |
|
115 | 115 | <Warning> |
116 | | - The relocation handoff uses a batched wire request. During a rolling upgrade, run homogeneous GoAkt versions before |
117 | | - triggering topology changes: an older node cannot process the batched request, and its share is then reassigned to |
118 | | - another peer or reported as failed. |
| 116 | + The relocation handoff uses a batched wire request. During a rolling upgrade, run homogeneous GoAkt versions before triggering topology |
| 117 | + changes: an older node cannot process the batched request, and its share is then reassigned to another peer or reported as failed. |
119 | 118 | </Warning> |
120 | 119 |
|
121 | 120 | ## Relocation events |
@@ -269,9 +268,8 @@ Set `WithReplicaCount(3)` to also tolerate two concurrent node losses, at the co |
269 | 268 | registry update. |
270 | 269 |
|
271 | 270 | <Warning> |
272 | | - With `WithReplicaCount(1)` there are no backups: the partitions owned by a crashed node are lost with it, and |
273 | | - registry-derived recovery silently misses the affected records. The actor system logs a warning at startup when |
274 | | - clustering runs with a replica count of 1. |
| 271 | + With `WithReplicaCount(1)` there are no backups: the partitions owned by a crashed node are lost with it, and registry-derived recovery |
| 272 | + silently misses the affected records. The actor system logs a warning at startup when clustering runs with a replica count of 1. |
275 | 273 | </Warning> |
276 | 274 |
|
277 | 275 | Cases that remain open at any replica count: losing all owners of a partition at once loses its records; a write |
@@ -328,9 +326,7 @@ identity, err := actor.GrainOf[*MyGrain](ctx, system, "my-grain", actor.WithGrai |
328 | 326 | Use this for grains that must stay warm without an external trigger (for example those driving timers, streams, or |
329 | 327 | background work) that must resume immediately after the host departs. |
330 | 328 |
|
331 | | -<Note> |
332 | | - `WithGrainEagerRelocation` and `WithGrainDisableRelocation` are mutually exclusive; configuring both fails validation. |
333 | | -</Note> |
| 329 | +<Note>`WithGrainEagerRelocation` and `WithGrainDisableRelocation` are mutually exclusive; configuring both fails validation.</Note> |
334 | 330 |
|
335 | 331 | ### Disable relocation system-wide |
336 | 332 |
|
@@ -392,12 +388,13 @@ Masking is bounded, not unbounded. Each node opens a short handoff window when i |
392 | 388 |
|
393 | 389 | - **ErrActorNotFound**: the actor could not be resolved on any surviving node. |
394 | 390 | - **ErrRelocationInProgress**: the target is still being relocated; retry shortly. |
395 | | - </Note> |
| 391 | + |
| 392 | +</Note> |
396 | 393 |
|
397 | 394 | <Warning> |
398 | | - Identity-based routing (`SendAsync` / `SendSync` and their `ReceiveContext` wrappers) re-resolves the target on each |
399 | | - send, so both observe the relocation. Holding a stale remote `*PID` obtained before the departure and calling `Tell` / |
400 | | - `Ask` on it directly bypasses re-resolution and can still surface a connection error, so resolve by name during churn. |
| 395 | + Identity-based routing (`SendAsync` / `SendSync` and their `ReceiveContext` wrappers) re-resolves the target on each send, so both observe |
| 396 | + the relocation. Holding a stale remote `*PID` obtained before the departure and calling `Tell` / `Ask` on it directly bypasses |
| 397 | + re-resolution and can still surface a connection error, so resolve by name during churn. |
401 | 398 | </Warning> |
402 | 399 |
|
403 | 400 | ## Check relocatability |
|
0 commit comments