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}