Tutorial · 15 min

Tracing a Pipeline End-to-End

Follow a feature from CLI entry point through HTTP boundary to database — 9 hops across 2 languages.

Follow along: This tutorial uses the Ix repo. If you haven’t already, clone it and map it:
git clone https://github.com/ix-infrastructure/Ix.git && cd Ix && ix map
We’ll trace the ingestion pipeline — the path code takes when you run ix map — but the technique works for any feature in any codebase.
01Find the Entry Point

Every CLI command has a registration function. Start there.

ix search registerIngestCommand --kind function
registerIngestCommand (function)
  ix-cli/src/cli/commands/ingest.ts:153-183
  tier: 0  matchSource: name_exact
02Follow What It Calls

callees shows what a function calls. Chain it to go deeper.

ix callees registerIngestCommand
# → ingestFiles, ingestGitHub

ix callees ingestFiles
# → loadExistingHashes, loadIngestionModules, flushBatch,
#   sha256, commitPreparedPatches, IxClient.commitPatchBatch, ...

Two branches from the entry: local ingestion and GitHub. Following the local path reveals the full pipeline: discover → parse → resolve edges → flush in batches.

03Read the Batching Logic

When you need implementation details, read the specific function.

ix read flushBatch
ix-cli/src/cli/commands/ingest.ts:340-383

 340 | const flushBatch = async (batch) => {
 341 |   if (batch.length === 0) return;
 342 |   const resolvedEdges = resolveEdgesFn!(batch.map(f => f.parsed));
 ...
 366 |   await commitPreparedPatches(client, patches);
 ...

Batches are prepared and sent via commitPreparedPatches, which handles the CLI → server boundary.

04Cross the HTTP Boundary

The same name often exists on both sides. Use --pick to disambiguate.

ix search commitPatch --kind function
# 1. commitPatch (method) — ix-cli/src/client/api.ts        ← CLI side
# 2. commitPatch (function) — ArangoGraphWriteApi.scala      ← server side

ix callees commitPatch --pick 2
# → beginTransaction, checkIdempotency, doCommit, commitTransaction
05Follow to the Database

Keep following callees to reach the bottom of the stack.

ix callees doCommit
# → loadLatestRev, loadActiveClaimsCache, executeOp,
#   retireAbsentClaimsBatch, storePatch, storeIdempotencyKey,
#   updateRevision, commitTransaction

executeOp is where AQL mutations actually hit ArangoDB. It handles 7 operation types: UpsertNode, UpsertEdge, DeleteNode, DeleteEdge, AssertClaim, RetractClaim. Nodes are tombstoned (soft-deleted with deleted_rev), not physically removed.

06Shortcut: Get the Full Tree

Instead of tracing hop-by-hop, depends --depth 3 gives you the full tree at once.

ix depends commitPatch --pick 2 --depth 3
commitPatch (ArangoGraphWriteApi.scala)
  └─ beginTransaction
  └─ checkIdempotency
  └─ doCommit
      └─ loadLatestRev
      └─ executeOp
          └─ client.execute (ArangoClient)
      └─ retireAbsentClaimsBatch
      └─ storePatch
      └─ updateRevision
  └─ commitTransaction
07The Complete Pipeline
registerIngestCommand           CLI entry point
  → ingestFiles                  filesystem walk + parse loop
    → loadIngestionModules       dynamic Tree-Sitter loading
    → flushBatch                 batch with fallback
      → commitPreparedPatches    prepare and send batch
        → IxClient.commitPatchBatch  HTTP POST (batch)
        → IxClient.commitPatch       HTTP POST (per-file fallback)
          ─── HTTP boundary ───
          → commitPatch           Scala REST handler
            → beginTransaction
            → checkIdempotency
            → doCommit
              → loadLatestRev
              → executeOp          7 AQL mutation cases
              → retireAbsentClaimsBatch
              → storePatch
              → updateRevision
            → commitTransaction

9 hops from CLI to database. Every hop discovered using callees, read, and search — no file browsing needed.

08Techniques
ix search X --kind functionFind the starting point
ix callees XFollow what a function calls (go deeper)
ix callers XFollow what calls a function (go higher)
ix read XRead source for implementation details
ix read X --pick NDisambiguate across files
ix depends X --depth 3Get the full tree instead of hop-by-hop