carlos / platform Public

Clone
git clone https://amadan.net/carlos/platform

Plain git — no account needed to clone.

Download

Download this file

1package activator
2
3import (
4 "fmt"
5
6 "github.com/carlosframework/platform/internal/registry"
7 "github.com/carlosframework/platform/internal/seeds"
8)
9
10// wakeRouteChanged is doWake's check of the row it refreshed against the
11// row the wake began from (final review F4). The edge admits a wake on its
12// cached row, which can be minutes behind the registry: an import's
13// rollback restores the legacy route and lifts its fence before the edge
14// reloads, and a verify request admitted on the cached import row would
15// then take the host's lease and restore its replica while the rollback
16// deletes that same prefix. A refreshed row that the activator no longer
17// manages, or that is now a different route (account, app, seed, import
18// gate or address), is not woken: the answer is an ordinary failed wake,
19// before any lease or restore. nil means the wake goes on.
20//
21// The shape is judged by the entry's own role (re-review finding 9): an
22// instance entry's row must still be ActivatorManaged, and a worker
23// entry's (WakeWorker, a standalone sidecar, which binds no socket) must
24// still be a sidecar. The identity checks hold for both.
25//
26// The activator also wakes instance rows that are not ActivatorManaged:
27// the edge hands it every hibernating instance row, so a unit-backed one
28// (SplitBackend's Unit half, which systemd runs) and a row with no socket
29// column (the backend derives its paths) are woken too. A wake that began
30// for such a row goes on while the refreshed row has the same shape
31// (stillWoken); the identity checks hold for it as well. No seed or import
32// is one of these rows: the swap refuses a row with a backing and installs
33// an ActivatorManaged one, so a wake that began on an import's row is
34// always held to ActivatorManaged, and the row a rollback puts back fails
35// it.
36func wakeRouteChanged(began, now registry.Route, worker bool) error {
37 switch {
38 case worker && !now.IsSidecar():
39 return fmt.Errorf("%s: the route changed before the wake: it is no longer a sidecar", now.Host)
40 case !worker && !stillWoken(began, now):
41 return fmt.Errorf("%s: the route changed before the wake: the activator no longer manages it", now.Host)
42 case began.Account != now.Account || began.App != now.App:
43 return fmt.Errorf("%s: the route changed before the wake: it belongs to %s/%s now, not %s/%s", now.Host, now.Account, now.App, began.Account, began.App)
44 case began.Addr != now.Addr:
45 return fmt.Errorf("%s: the route changed before the wake: its address is %q now, not %q", now.Host, now.Addr, began.Addr)
46 case began.ImportGate != now.ImportGate:
47 return fmt.Errorf("%s: the route changed before the wake: its import gate changed", now.Host)
48 case rowSeedID(began.SeedSource) != rowSeedID(now.SeedSource):
49 return fmt.Errorf("%s: the route changed before the wake: its seed is %q now, not %q", now.Host, rowSeedID(now.SeedSource), rowSeedID(began.SeedSource))
50 }
51 return nil
52}
53
54// stillWoken reports whether now is still a row an instance entry's wake,
55// begun for began, may go on with. A wake that began on an ActivatorManaged
56// row needs one still. Any other row the activator was handed must be an
57// instance row and keep the shape it began with, in the fields
58// ActivatorManaged reads: its hibernate flag, whether it has a socket, its
59// backing and its tunnel. A sidecar's row is never an instance entry's.
60func stillWoken(began, now registry.Route) bool {
61 if ActivatorManaged(began) {
62 return ActivatorManaged(now)
63 }
64 return now.Kind == "instance" && began.Kind == now.Kind && began.Hibernate == now.Hibernate &&
65 (began.Socket != "") == (now.Socket != "") &&
66 began.Backing == now.Backing && began.Tunnel == now.Tunnel
67}
68
69// rowSeedID is the seed a row's seed column names: its id, "" for none, and
70// the column itself when it does not parse. A seed's state moves on while
71// it is the same seed (ready, placed, committed), so only the id is the
72// row's identity.
73func rowSeedID(col string) string {
74 rs, err := seeds.ParseRowSeed(col)
75 switch {
76 case err != nil:
77 return col
78 case rs == nil:
79 return ""
80 }
81 return rs.ID
82}
83