feat(workspace): tabula-rasa outliner architecture, SQLite blocks/block_tags schema & echo-protected live room sync
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 1m12s
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 1m12s
This commit is contained in:
1 parent
f3b3f07e04
commit
86867b0d6f
17 files changed
+3409
-7178
No files matched your search
@@ -683,9 +683,9 @@ func TestDatabaseFirstWorkspaceArchitecture(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestDocumentCRDTState(t *testing.T) {
|
||||
func TestFlushDocumentStateAndSchema(t *testing.T) {
|
||||
tmpDir := t.TempDir()
|
||||
dbPath := filepath.Join(tmpDir, "crdt_test.db")
|
||||
dbPath := filepath.Join(tmpDir, "tabula_rasa_test.db")
|
||||
|
||||
store, err := NewStore(dbPath)
|
||||
if err != nil {
|
||||
@@ -693,52 +693,60 @@ func TestDocumentCRDTState(t *testing.T) {
|
||||
}
|
||||
defer store.Close()
|
||||
|
||||
user, err := store.CreateUser("crdt@example.com", "hash", "CRDT User", "member")
|
||||
user, err := store.CreateUser("outliner@example.com", "hash", "Outliner User", "member")
|
||||
if err != nil {
|
||||
t.Fatalf("CreateUser failed: %v", err)
|
||||
}
|
||||
|
||||
doc, err := store.CreateDocument(user.ID, "", "CRDT Test Doc", "📝", "", nil, nil, false)
|
||||
doc, err := store.CreateDocument(user.ID, "", "Initial Note", "📝", "Projekte", nil, nil, false)
|
||||
if err != nil {
|
||||
t.Fatalf("CreateDocument failed: %v", err)
|
||||
}
|
||||
|
||||
// 1. Initial CRDT state is empty
|
||||
state, updates, err := store.GetDocumentCRDTState(doc.ID)
|
||||
blocks := []domain.DocumentBlock{
|
||||
{
|
||||
ID: "blk_root_1",
|
||||
Type: "text",
|
||||
Content: "Architektur Übersicht #backend #go",
|
||||
Level: 0,
|
||||
},
|
||||
{
|
||||
ID: "blk_child_1",
|
||||
Type: "todo",
|
||||
Content: "SQLite WAL Modus aktivieren #sqlite",
|
||||
Level: 1,
|
||||
Checked: true,
|
||||
},
|
||||
}
|
||||
|
||||
if err := store.FlushDocumentState(doc.ID, "Architektur Notiz", blocks); err != nil {
|
||||
t.Fatalf("FlushDocumentState failed: %v", err)
|
||||
}
|
||||
|
||||
updatedDoc, err := store.GetDocumentByID(user.ID, doc.ID)
|
||||
if err != nil {
|
||||
t.Fatalf("GetDocumentCRDTState failed: %v", err)
|
||||
t.Fatalf("GetDocumentByID failed: %v", err)
|
||||
}
|
||||
if len(state) != 0 || len(updates) != 0 {
|
||||
t.Fatalf("expected empty CRDT state, got state=%d updates=%d", len(state), len(updates))
|
||||
if updatedDoc.Title != "Architektur Notiz" {
|
||||
t.Fatalf("expected title 'Architektur Notiz', got '%s'", updatedDoc.Title)
|
||||
}
|
||||
if len(updatedDoc.Blocks) != 2 {
|
||||
t.Fatalf("expected 2 blocks, got %d", len(updatedDoc.Blocks))
|
||||
}
|
||||
if updatedDoc.Blocks[1].Level != 1 || updatedDoc.Blocks[1].Position != 2000 {
|
||||
t.Fatalf("expected block[1] level=1 position=2000, got level=%d position=%v", updatedDoc.Blocks[1].Level, updatedDoc.Blocks[1].Position)
|
||||
}
|
||||
if updatedDoc.MarkdownCache == "" {
|
||||
t.Fatalf("expected markdown_cache to be populated")
|
||||
}
|
||||
|
||||
// 2. Append incremental updates
|
||||
u1 := []byte{1, 2, 3, 4}
|
||||
u2 := []byte{5, 6, 7, 8}
|
||||
if err := store.AppendDocumentCRDTUpdate(doc.ID, u1, user.ID); err != nil {
|
||||
t.Fatalf("AppendDocumentCRDTUpdate 1 failed: %v", err)
|
||||
}
|
||||
if err := store.AppendDocumentCRDTUpdate(doc.ID, u2, user.ID); err != nil {
|
||||
t.Fatalf("AppendDocumentCRDTUpdate 2 failed: %v", err)
|
||||
}
|
||||
|
||||
_, updatesAfter, err := store.GetDocumentCRDTState(doc.ID)
|
||||
if err != nil || len(updatesAfter) != 2 {
|
||||
t.Fatalf("expected 2 updates, got %d (err: %v)", len(updatesAfter), err)
|
||||
}
|
||||
|
||||
// 3. Compact snapshot state
|
||||
snapshot := []byte{99, 100, 101}
|
||||
if err := store.SaveDocumentCRDTState(doc.ID, snapshot, user.ID); err != nil {
|
||||
t.Fatalf("SaveDocumentCRDTState failed: %v", err)
|
||||
}
|
||||
|
||||
stateAfter, updatesAfterCompact, err := store.GetDocumentCRDTState(doc.ID)
|
||||
tags, err := store.GetWorkspaceTags(user.ID)
|
||||
if err != nil {
|
||||
t.Fatalf("GetDocumentCRDTState after compact failed: %v", err)
|
||||
t.Fatalf("GetWorkspaceTags failed: %v", err)
|
||||
}
|
||||
if len(stateAfter) != 3 || len(updatesAfterCompact) != 0 {
|
||||
t.Fatalf("expected compacted state of length 3 and 0 updates, got state=%d updates=%d", len(stateAfter), len(updatesAfterCompact))
|
||||
if len(tags) != 3 {
|
||||
t.Fatalf("expected 3 extracted tags in block_tags (#backend, #go, #sqlite), got %d: %+v", len(tags), tags)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user