fix: use persistent maps for STM state store — fixes corruption under load

ober

fc1c905c503dfcd00838c57282aca0e7645928bd

diff --git a/edge.ss b/edge.ss
index 96e5c54..7a09447 100644
--- a/edge.ss
+++ b/edge.ss
@@ -32,7 +32,8 @@
         (std stm)
         (std transducer)
         (std text json)
-        (std crypto native))
+        (std crypto native)
+        (std pmap))
 
 ;; ═══════════════════════════════════════════════════════════════
 ;; Configuration
@@ -61,28 +62,29 @@
 ;; atomic and produces an immutable snapshot — no locks, no races.
 ;; ═══════════════════════════════════════════════════════════════
 
-(def events-ref  (make-ref (make-hash-table)))
+(def events-ref  (make-ref (make-persistent-map)))
 (def watchers-ref (make-ref '()))
 
 (def (store-result! event status)
   (dosync
     (alter events-ref
       (lambda (st)
-        (hash-put! st (hash-ref event "id")
+        (persistent-map-set st (hash-ref event "id")
           (list->hash-table
             `(("type"      . ,(hash-ref event "type"))
               ("status"    . ,status)
               ("received"  . ,(hash-ref event "received"))
-              ("processed" . ,(format "~a" (time-second (current-time)))))))
-        st))))
+              ("processed" . ,(format "~a" (time-second (current-time)))))))))))
 
 (def (get-event id)
-  (hash-get (ref-deref events-ref) id))
+  (let ([st (ref-deref events-ref)])
+    (and (persistent-map-has? st id)
+         (persistent-map-ref st id))))
 
 (def (event-stats)
   (let ([st (ref-deref events-ref)]
         [total 0] [ok-n 0] [err-n 0])
-    (hash-for-each
+    (persistent-map-for-each
       (lambda (id record)
         (set! total (+ total 1))
         (if (string=? (hash-ref record "status" "") "ok")