# Troubleshooting Coding and Queries

This guide covers common issues and performance tips when working with custom code and queries in Curiosity Workspace.

# Deadlocking

Deadlocks occur when two concurrent operations wait for each other to release a lock, causing both to freeze.

# Common Causes

  1. Inconsistent Locking Order:
    • Thread A locks Node 1, then tries to lock Node 2.
    • Thread B locks Node 2, then tries to lock Node 1.
  2. Long-held Locks: Holding a lock while performing long network requests or heavy computation increases the window for conflicts.

# Solutions

  • Consistent Ordering: If you need to lock multiple nodes, always sort them by their UID before acquiring locks.

    // CORRECT: Consistent order prevents deadlocks
    var uidsToLock = new[] { uidA, uidB }.OrderBy(u => u).ToList();
    // Lock in this order
    // WRONG: Locking in arbitrary order
    await Graph.GetOrAddLockedAsync(uidA);
    // ... some work ...
    await Graph.GetOrAddLockedAsync(uidB); // Risk of deadlock if another thread locked B then A
  • Lock Late, Commit Early: Acquire locks immediately before you need to modify data, and call CommitAsync as soon as the modification is done.

  • Avoid Expensive Operations Inside Locks: Do not perform network requests or heavy calculations while holding a lock.

    // WRONG
    var node = await Graph.GetOrAddLockedAsync(uid);
    var data = await CallSlowExternalApi(); // Slow! Blocks other threads needing 'node'
    node.UpdateProperty("data", data);
    await Graph.CommitAsync(node);
    
    // CORRECT
    var data = await CallSlowExternalApi(); // Do slow work first
    var node = await Graph.GetOrAddLockedAsync(uid); // Lock briefly
    node.UpdateProperty("data", data);
    await Graph.CommitAsync(node);

# Uncommitted Nodes

One of the most common errors is forgetting to commit a locked node.

var node = await Graph.GetOrAddLockedAsync(uid);
node.UpdateProperty("status", "processing");

// ... exception thrown here ...

// Commit is never reached! Node remains locked forever (until restart).
await Graph.CommitAsync(node);

Fix: Use try/finally or ensure code paths are safe. If an endpoint finishes and a node is still locked, the system will eventually detect it, abandon the changes, and throw an exception to warn you, but this causes instability.

# Performance Optimization

Curiosity's GraphDB is an in-memory graph database, but understanding its performance characteristics is crucial for writing efficient code.

# Edge Traversal is Fast

Relationships are stored as direct memory pointers. Operations like Out(), IsRelatedTo(), and SortByConnectivity() are extremely fast because they traverse these pointers without deserializing data.

# Property Access can be Slower

Reading a property value (e.g., node.GetString("name")) involves deserializing the node's content blob. While fast, doing this for millions of nodes in a loop is significantly slower than edge traversal.

Implication:

  • Avoid Where(n => n.GetString("status") == "Active") if possible. This forces the engine to load and deserialize every node to check the property.
  • Instead, use WhereString("status", "Active"). This uses internal indexes to filter UIDs before loading the content.

# Indexing

  • Exact Match: Use StartWhereString or WhereString to leverage hash indexes for exact value lookups.
  • Full Text: Use StartSearch for fuzzy matching or relevance-based search. This uses the inverted index.

# Large Result Sets

If a query returns thousands of nodes:

  • Don't use ToList() immediately if you don't need all data in memory.
  • Do use AsEnumerableAsync() to stream results.
  • Do use Take() and Skip() for pagination.

# Common Exceptions

Exception Cause Fix
RequestedAlreadyLockedNodeException You tried to lock a node that is already locked by another thread (or your own thread in a different context). Use retry logic or review locking strategy.
DeadlockHadToBePreventedException The system detected a potential deadlock or unreleased lock. Check for missing CommitAsync calls.
NodeNotFoundException You tried to perform an operation on a UID that doesn't exist. Check if the node exists using Graph.HasNode(uid) before proceeding.