AtlatestRepositoryfolio

folio / tree / testtest-writer-serialization.sgl

1;;; A mutation remains serialized through its delayed index flush.
2(import (sigil test)
3 (sigil fs)
4 (sigil path)
5 (sigil string)
6 (sigil async)
7 (sigil channels)
8 (sigil time)
9 (sigil sqlite)
10 (sigil mcp server)
11 (sigil mcp protocol)
12 (folio store)
13 (folio index)
14 (folio tools))
16(test-group "whole writer serialization"
17 (test "a second mutation waits until the first index flush finishes"
18 (call-with-temp-directory
19 (lambda (root)
20 (let* ((store (make-folio-store root))
21 (file (path-join (store-notes-dir store) "writer.md"))
22 (_ (write-file-string file "# Writer\n"))
23 (idx (make-folio-index store))
24 (_ (index-census-tick! idx))
25 (server (mcp-server name: "writer-test"))
26 (ready (make-channel 1))
27 (release (make-channel 1))
28 (done (make-channel 2))
29 (first-visible? #f)
30 (second-waited? #f))
31 (define (append! id marker)
32 (let ((reply (mcp-server-handle-message server
33 (jsonrpc-request id: id method: "tools/call"
34 params: (dict name: "folio/note-edit"
35 arguments: (dict name: "writer" append: marker))))))
36 (channel-send done reply)))
37 (register-folio-tools! server store idx)
38 (with-async
39 (go
40 (with-index-transaction idx
41 (lambda ()
42 (channel-send ready #t)
43 (channel-receive release))))
44 (go
45 (channel-receive ready)
46 (go (append! 1 "first-marker\n"))
47 (let wait ((attempt 0))
48 (unless (or (string-contains? (read-file-string file) "first-marker")
49 (= attempt 200))
50 (sleep 0.01)
51 (wait (+ attempt 1))))
52 (set! first-visible? (string-contains? (read-file-string file) "first-marker"))
53 (go (append! 2 "second-marker\n"))
54 (sleep 0.1)
55 (set! second-waited? (not (string-contains? (read-file-string file) "second-marker")))
56 (channel-send release #t)
57 (assert-true (jsonrpc-response? (channel-receive done)))
58 (assert-true (jsonrpc-response? (channel-receive done)))))
59 (display (format "WRITER gate first-visible=~a second-waited=~a\n"
60 first-visible? second-waited?))
61 (assert-true first-visible?)
62 (assert-true second-waited?)
63 (let ((content (read-file-string file)))
64 (assert-true (string-contains? content "first-marker"))
65 (assert-true (string-contains? content "second-marker")))
66 (sqlite-close (folio-index-db idx)))))))