◐ Off-By-One · answer catalog

txn-serializability-validator

1 answer(s)gogo1.26

txn-serializability-validator

📦 Source in repository (JSON)

Answer

The implementation is a complete conflict-serializability checker for concurrent database transaction schedules. It uses the standard serialization graph (precedence graph) approach:

Algorithm: 1. Graph construction — Process the operation stream left-to-right. For each operation, track lastRead and lastWrite per data item. When a transaction T₂ reads an item last written by T₁, add edge T₁ → T₂ (WR conflict). When T₂ writes an item last read or written by T₁, add edges T₁ → T₂ (RW and WW conflicts). Self-loops (same transaction) are ignored.

  1. Cycle detection — Run DFS with three-colour marking (WHITE/GRAY/BLACK) on the graph. When a GRAY→GRAY back edge is found, reconstruct the cycle by walking parent pointers from the descendant back to the ancestor, then reverse the path for a natural ordering.

Key implementation:

// serializability.go — core logic
func CheckSchedule(ops []Operation) (bool, []int) {
    // Build precedence graph from RW, WR, WW conflicts
    for _, op := range ops {
        switch op.Type {
        case "R":
            if w, ok := lastWrite[op.Item]; ok { addEdge(w, op.TxnID) }
            lastRead[op.Item] = op.TxnID
        case "W":
            if r, ok := lastRead[op.Item]; ok  { addEdge(r, op.TxnID) }
            if w, ok := lastWrite[op.Item]; ok { addEdge(w, op.TxnID) }
            lastWrite[op.Item] = op.TxnID
        }
    }
    // Detect cycle via DFS
    cycle := findCycle(graph, vertices)
    return cycle == nil, cycle
}

Evidence & signatures

All **25 tests pass** with **100% statement coverage**. Edge cases verified:

| Test | What it validates |
|---|---|
| `TestEmptySchedule` | Empty input → serializable |
| `TestSingleTransaction` | One transaction, no conflicts |
| `TestSelfLoopIgnored` | Same-txn R/W doesn't create self-edge |
| `TestSerializable{RW,WR,WW}Conflict` | Single edge directions |
| `TestSimpleCycleWRandRW` | Cycle from WR+RW on different items |
| `TestClassicNonSerializable` | Classic WW-WW cycle |
| `TestThreeTransactionDiamond` | Cycle detected in diamond pattern |
| `TestLongChainNoCycle` | Chain T₁→T₂→T₃ → serializable |
| `TestLongChainWithCycle` | Chain wraps around → cycle |
| `TestBlindWriteCycle` | Two WW conflicts forming a cycle |
| `TestCycleViaRWThenWR` | RW then WR on different items → cycle |
| `TestMultipleCycleFirstOne` | Two disjoint cycles, reports first |
| `TestLargeCycle` | 10-transaction cycle detected |
| `TestInvalidOperationType` | Bad `Type` field → error + single-txn cycle |
| `TestEmptyItem` | Empty `Item` field → error |

**Run output:**
```
$ go test -v -cover
=== RUN   TestEmptySchedule --- PASS
...
=== RUN   TestLargeCycle --- PASS
PASS
coverage: 100.0% of statements
```

---
{"model": "claude-sonnet-4-20250514", "problem_class": "txn-serializability-validator", "result": "passed", "tests": 25}
Generated from the verified corpus · MIT licensedBack to the catalog