code wiki / _hdl_build / nx_relate_live_gate.nx
nx_relate_live_gate.nx source
↩ module page · 142 lines · 6529 B
1// nx_relate_live_gate.nx -- LIVE: the Relationship OS over a REAL HTTP socket (loopback fork gate, the exact
2// nx_email_webmail_gate pattern). Seeds the store (Rose + Andelin West + a works-at edge), then fork:
3// parent = the server: accept 3 connections -> rv_read_req -> rv_handle -> rv_write_all
4// child = a real HTTP/1.1 client:
5// 1. GET / -> HTML lists the SEEDED graph ("Rose Andelin" + the edge role "Managing Partner")
6// 2. POST /add-entity -> form body type=org&name=First+Ward&tenant=personal; redraw shows "First Ward"
7// 3. GET / -> still shows Rose AND First Ward (persisted across connections)
8// Then the parent verifies the STORE really grew (entities == 3). ONE fork (degraded-box discipline).
9// Evidence -> knowledge/status/relate_live.log (RELATELIVEGATE ... verdict=GREEN)
10// expect_exit: 0 license_tier: ORIGINAL
11import "nx_relate_serve.nx"
12
13import "nx_connect.nx" // bounded connect: a raw sys_connect hangs ~127s on a black-holed host
14const RL_PORT: i64 = 0x2557
15const RL_LOG: *u8 = "knowledge/status/relate_live.log"
16
17func g_addr(out: *u8, port: i64) -> i64 {
18 out[0] = 2 as u8; out[1] = 0 as u8
19 out[2] = ((port >> 8) & 0xff) as u8; out[3] = (port & 0xff) as u8
20 out[4] = 127 as u8; out[5] = 0 as u8; out[6] = 0 as u8; out[7] = 1 as u8
21 var i: i64 = 8
22 while i < 16 { out[i] = 0 as u8; i = i + 1 }
23 return 0
24}
25func g_writes(fd: i64, s: *u8) -> i64 {
26 var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 }
27 return rv_write_all(fd, s, n)
28}
29// one HTTP exchange: send the full request string, read the whole response (server closes).
30func http_req(addr: *u8, req: *u8, out: *u8, cap: i64) -> i64 {
31 let cfd: i64 = sys_socket(AF_INET, SOCK_STREAM, 0)
32 if cfd < 0 { return 0 - 1 }
33 if nx_connect_bounded(cfd, addr, 16, NX_CONN_DEFAULT_MS) < 0 { sys_close(cfd); return 0 - 2 }
34 if g_writes(cfd, req) < 0 { sys_close(cfd); return 0 - 3 }
35 var n: i64 = 0
36 var go: i64 = 1
37 while go == 1 {
38 if n >= cap - 1 { go = 0 } else {
39 let r: i64 = sys_read(cfd, (out as i64 + n) as *u8, cap - 1 - n)
40 if r <= 0 { go = 0 } else { n = n + r }
41 }
42 }
43 sys_close(cfd)
44 return n
45}
46
47func g_run_client(addr: *u8) -> i64 {
48 var spin: i64 = 0
49 while spin < 400000 { spin = spin + 1 }
50 let buf: *u8 = sys_mmap(262144)
51 // 1. GET / -> seeded graph rendered from the persisted store
52 let n1: i64 = http_req(addr, "GET / HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n" as *u8, buf, 262144)
53 if n1 <= 0 { return 11 }
54 if rv_has(buf, n1, "Rose Andelin" as *u8) != 1 { return 12 }
55 if rv_has(buf, n1, "Managing Partner" as *u8) != 1 { return 13 }
56 if rv_has(buf, n1, "First Ward" as *u8) != 0 { return 14 } // not yet added
57 // 2. POST /add-entity (body = 40 bytes) -> redraw shows the new org
58 let post: *u8 = "POST /add-entity HTTP/1.1\r\nHost: localhost\r\nContent-Length: 40\r\nConnection: close\r\n\r\ntype=org&name=First+Ward&tenant=personal" as *u8
59 let n2: i64 = http_req(addr, post, buf, 262144)
60 if n2 <= 0 { return 15 }
61 if rv_has(buf, n2, "First Ward" as *u8) != 1 { return 16 }
62 // 3. GET / -> BOTH persist across connections
63 let n3: i64 = http_req(addr, "GET / HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n" as *u8, buf, 262144)
64 if n3 <= 0 { return 17 }
65 if rv_has(buf, n3, "Rose Andelin" as *u8) != 1 { return 18 }
66 if rv_has(buf, n3, "First Ward" as *u8) != 1 { return 19 }
67 return 0
68}
69
70func main() -> i64 {
71 // fresh store prefix for this run
72 let prefix: *u8 = sys_mmap(128)
73 var po: i64 = 0
74 po = rv_cat(prefix, po, "/tmp/rellive_" as *u8)
75 po = rv_catn(prefix, po, sys_now_us())
76 po = rv_cat(prefix, po, "_" as *u8)
77 prefix[po] = 0 as u8
78
79 // seed: 2 entities + 1 edge
80 let w: *i64 = ss_begin()
81 rv_save_entity(w, "person" as *u8, "Rose Andelin" as *u8, "andelinwest" as *u8)
82 rv_save_entity(w, "company" as *u8, "Andelin West" as *u8, "andelinwest" as *u8)
83 rv_save_edge(w, "Rose Andelin" as *u8, "works-at" as *u8, "Andelin West" as *u8, "professional" as *u8, "Managing Partner" as *u8)
84 if ss_commit(prefix, w, sys_now_us()) != 0 { p("RELATELIVEGATE seed FAILED verdict=RED\n" as *u8); sys_exit(92); return 92 }
85
86 let addr: *u8 = sys_mmap(16)
87 g_addr(addr, RL_PORT)
88 let lfd: i64 = sys_socket(AF_INET, SOCK_STREAM, 0)
89 if lfd < 0 { sys_exit(93); return 93 }
90 if sys_bind(lfd, addr, 16) < 0 { sys_exit(94); return 94 }
91 if sys_listen(lfd, 8) < 0 { sys_exit(95); return 95 }
92
93 let pid: i64 = sys_fork()
94 if pid < 0 { sys_exit(96); return 96 }
95 if pid == 0 {
96 let crc: i64 = g_run_client(addr)
97 sys_exit(crc); return crc
98 }
99
100 // parent = the server: 3 connections
101 let reqb: *u8 = sys_mmap(65536)
102 let resb: *u8 = sys_mmap(262144)
103 var served: i64 = 0
104 while served < 3 {
105 let scfd: i64 = sys_accept(lfd)
106 if scfd < 0 { served = 3 } else {
107 let rn: i64 = rv_read_req(scfd, reqb, 65536)
108 let on: i64 = rv_handle(prefix, reqb, rn, resb, 262144)
109 rv_write_all(scfd, resb, on)
110 sys_close(scfd)
111 served = served + 1
112 }
113 }
114
115 let status: *i64 = sys_mmap(8) as *i64
116 sys_wait4(pid, status, 0)
117 let child_code: i64 = (status[0] >> 8) & 0xff
118
119 // the store really grew (2 seeded + 1 POSTed)
120 let ents: i64 = rv_count_ent(prefix)
121 var store_ok: i64 = 0
122 if ents == 3 { store_ok = 1 }
123
124 var green: i64 = 0
125 if child_code == 0 && store_ok == 1 { green = 1 }
126
127 var fd: i64 = 1
128 while fd >= 1 {
129 g_writes(fd, "RELATELIVEGATE authored=organ http=loopback " as *u8)
130 if child_code == 0 { g_writes(fd, "get_renders_store=PASS post_adds=PASS persist_across_conns=PASS " as *u8) }
131 else { g_writes(fd, "client_checks=FAIL code=" as *u8); let d: *u8 = sys_mmap(8); d[0] = (48 + (child_code / 10)) as u8; d[1] = (48 + (child_code % 10)) as u8; d[2] = 32 as u8; d[3] = 0 as u8; g_writes(fd, d) }
132 if store_ok == 1 { g_writes(fd, "store_entities=3=PASS " as *u8) } else { g_writes(fd, "store_entities=FAIL " as *u8) }
133 if green == 1 { g_writes(fd, "verdict=GREEN\n" as *u8) } else { g_writes(fd, "verdict=RED\n" as *u8) }
134 if fd == 1 {
135 let lf: i64 = sys_openat_append(RL_LOG, 420)
136 if lf >= 1 { fd = lf } else { fd = 0 }
137 } else { sys_close(fd); fd = 0 }
138 }
139
140 if green == 1 { sys_exit(0); return 0 }
141 sys_exit(1); return 1
142}