<!-- CANARY: REQ=REQ-DOCS-001; FEATURE="Docs"; ASPECT=Documentation; STATUS=TESTED; OWNER=docs; UPDATED=2026-01-15 --> <p>The <strong>Development &amp; Developer Tools</strong> category encompasses comprehensive resources for building applications with Geode graph database. From initial setup through production deployment, these resources cover the complete development lifecycle with practical guides, API references, and tooling documentation.</p> <h3 id="introduction" class="position-relative d-flex align-items-center group"> <span>Introduction</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="introduction" aria-haspopup="dialog" aria-label="Share link: Introduction"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h3><div id="headingShareModal" class="heading-share-modal" role="dialog" aria-modal="true" aria-labelledby="headingShareTitle" hidden> <div class="hsm-dialog" role="document"> <div class="hsm-header"> <h2 id="headingShareTitle" class="h6 mb-0 fw-bold">Share this section</h2> <button type="button" class="hsm-close" aria-label="Close"> <i class="fa-solid fa-xmark"></i> </button> </div> <div class="hsm-body"> <label for="headingShareInput" class="form-label small text-muted mb-1 text-uppercase fw-bold" style="font-size: 0.7rem; letter-spacing: 0.5px;">Permalink</label> <div class="input-group mb-4 hsm-url-group"> <input id="headingShareInput" type="text" class="form-control font-monospace" readonly aria-readonly="true" style="font-size: 0.85rem;" /> <button class="btn btn-primary hsm-copy" type="button" aria-label="Copy" title="Copy"> <i class="fa-duotone fa-clipboard" aria-hidden="true"></i> </button> </div> <div class="small fw-bold mb-2 text-muted text-uppercase" style="font-size: 0.7rem; letter-spacing: 0.5px;">Share via</div> <div class="hsm-share-grid"> <a id="share-twitter" class="btn btn-outline-secondary w-100" target="_blank" rel="noopener noreferrer"> <i class="fa-brands fa-twitter me-2"></i>Twitter </a> <a id="share-linkedin" class="btn btn-outline-secondary w-100" target="_blank" rel="noopener noreferrer"> <i class="fa-brands fa-linkedin me-2"></i>LinkedIn </a> <a id="share-facebook" class="btn btn-outline-secondary w-100" target="_blank" rel="noopener noreferrer"> <i class="fa-brands fa-facebook me-2"></i>Facebook </a> </div> </div> </div> </div> <style> .heading-share-modal { position: fixed; inset: 0; display: flex; justify-content: center; align-items: center; background: rgba(0, 0, 0, 0.6); z-index: 1050; padding: 1rem; backdrop-filter: blur(4px); -webkit-backdrop-filter: blur(4px); } .heading-share-modal[hidden] { display: none !important; } .hsm-dialog { max-width: 420px; width: 100%; background: var(--bs-body-bg, #fff); color: var(--bs-body-color, #212529); border: 1px solid var(--bs-border-color, rgba(0,0,0,0.1)); border-radius: 1rem; box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25); overflow: hidden; animation: hsm-fade-in 0.2s ease-out; } @keyframes hsm-fade-in { from { opacity: 0; transform: scale(0.95); } to { opacity: 1; transform: scale(1); } } [data-bs-theme="dark"] .hsm-dialog { background: #1e293b; border-color: rgba(255,255,255,0.1); color: #f8f9fa; } .hsm-header { display: flex; justify-content: space-between; align-items: center; padding: 1rem 1.5rem; border-bottom: 1px solid var(--bs-border-color, rgba(0,0,0,0.1)); background: rgba(0,0,0,0.02); } [data-bs-theme="dark"] .hsm-header { background: rgba(255,255,255,0.02); border-color: rgba(255,255,255,0.1); } .hsm-close { background: transparent; border: none; color: inherit; opacity: 0.5; padding: 0.25rem 0.5rem; border-radius: 0.25rem; font-size: 1.2rem; line-height: 1; transition: opacity 0.2s; } .hsm-close:hover { opacity: 1; } .hsm-body { padding: 1.5rem; } .hsm-url-group { display: flex !important; align-items: stretch; } .hsm-url-group .form-control { flex: 1; min-width: 0; margin: 0; background: var(--bs-secondary-bg, #f8f9fa); border-color: var(--bs-border-color, #dee2e6); border-top-right-radius: 0; border-bottom-right-radius: 0; height: 42px; } .hsm-url-group .btn { flex: 0 0 auto; margin: 0; margin-left: -1px; border-top-left-radius: 0; border-bottom-left-radius: 0; height: 42px; display: flex; align-items: center; justify-content: center; padding: 0 1.25rem; z-index: 2; } [data-bs-theme="dark"] .hsm-url-group .form-control { background: #0f172a; border-color: #334155; color: #e2e8f0; } .hsm-share-grid { display: flex; flex-direction: column; gap: 0.5rem; } .hsm-share-grid .btn { display: flex; align-items: center; justify-content: center; font-size: 0.9rem; padding: 0.6rem; border-color: var(--bs-border-color); width: 100%; } [data-bs-theme="dark"] .hsm-share-grid .btn { color: #e2e8f0; border-color: #475569; } [data-bs-theme="dark"] .hsm-share-grid .btn:hover { background: #334155; border-color: #cbd5e1; } </style> <script> (function(){ const modal = document.getElementById('headingShareModal'); if(!modal) return; const input = modal.querySelector('#headingShareInput'); const copyBtn = modal.querySelector('.hsm-copy'); const twitter = modal.querySelector('#share-twitter'); const linkedin = modal.querySelector('#share-linkedin'); const facebook = modal.querySelector('#share-facebook'); const closeBtn = modal.querySelector('.hsm-close'); let lastFocus=null; let trapBound=false; function buildUrl(id){ return window.location.origin + window.location.pathname + '#' + id; } function isOpen(){ return !modal.hasAttribute('hidden'); } function hydrate(id){ const url=buildUrl(id); input.value=url; const enc=encodeURIComponent(url); const text=encodeURIComponent(document.title); if(twitter) twitter.href=`https://twitter.com/intent/tweet?url=${enc}&text=${text}`; if(linkedin) linkedin.href=`https://www.linkedin.com/sharing/share-offsite/?url=${enc}`; if(facebook) facebook.href=`https://www.facebook.com/sharer/sharer.php?u=${enc}`; } function openModal(id){ lastFocus=document.activeElement; hydrate(id); if(!isOpen()){ modal.removeAttribute('hidden'); } requestAnimationFrame(()=>{ input.focus(); }); trapFocus(); } function closeModal(){ if(!isOpen()) return; modal.setAttribute('hidden',''); if(lastFocus && typeof lastFocus.focus==='function') lastFocus.focus(); } function copyCurrent(){ try{ navigator.clipboard.writeText(input.value).then(()=>feedback(true),()=>fallback()); } catch(e){ fallback(); } } function fallback(){ input.select(); try{ document.execCommand('copy'); feedback(true);}catch(e){ feedback(false);} } function feedback(ok){ if(!copyBtn) return; const icon=copyBtn.querySelector('i'); if(!icon) return; const prev=copyBtn.getAttribute('data-prev')||icon.className; if(!copyBtn.getAttribute('data-prev')) copyBtn.setAttribute('data-prev',prev); icon.className= ok ? 'fa-duotone fa-clipboard-check':'fa-duotone fa-circle-exclamation'; setTimeout(()=>{ icon.className=prev; },1800); } function handleShareClick(e){ e.preventDefault(); const btn=e.currentTarget; const id=btn.getAttribute('data-share-target'); if(id) openModal(id); } function bindShareButtons(){ document.querySelectorAll('.h-share').forEach(btn=>{ if(!btn.dataset.hShareBound){ btn.addEventListener('click', handleShareClick); btn.dataset.hShareBound='1'; } }); } bindShareButtons(); if(document.readyState==='loading'){ document.addEventListener('DOMContentLoaded', bindShareButtons); } else { requestAnimationFrame(bindShareButtons); } document.addEventListener('click', function(e){ const shareBtn=e.target.closest && e.target.closest('.h-share'); if(shareBtn && !shareBtn.dataset.hShareBound){ handleShareClick.call(shareBtn, e); } }, true); document.addEventListener('click', e=>{ if(e.target===modal) closeModal(); if(e.target.closest && e.target.closest('.hsm-close')){ e.preventDefault(); closeModal(); } if(copyBtn && (e.target===copyBtn || (e.target.closest && e.target.closest('.hsm-copy')))) { e.preventDefault(); copyCurrent(); } }); document.addEventListener('keydown', e=>{ if(e.key==='Escape' && isOpen()) closeModal(); }); function trapFocus(){ if(trapBound) return; trapBound=true; modal.addEventListener('keydown', f=>{ if(f.key==='Tab' && isOpen()){ const focusable=[...modal.querySelectorAll('a[href],button,input,textarea,select,[tabindex]:not([tabindex="-1"])')].filter(el=>!el.hasAttribute('disabled')); if(!focusable.length) return; const first=focusable[0]; const last=focusable[focusable.length-1]; if(f.shiftKey && document.activeElement===first){ f.preventDefault(); last.focus(); } else if(!f.shiftKey && document.activeElement===last){ f.preventDefault(); first.focus(); } } }); } if(closeBtn) closeBtn.addEventListener('click', e=>{ e.preventDefault(); closeModal(); }); })(); </script><p>Modern database development requires more than just query capabilities—developers need rich tooling, intuitive APIs, and streamlined workflows. Geode provides a complete development ecosystem designed for productivity and ease of use. The REPL shell enables interactive query development with syntax highlighting and auto-completion. Client libraries for Go, Python, Rust, Node.js, and Zig offer idiomatic APIs for each language. LSP integration brings IDE features like error checking and go-to-definition to any editor. CLI tools automate common tasks from schema management to deployment.</p> <p>This category documents the full development experience, from writing your first query in the REPL to building production applications with client libraries. Whether you&rsquo;re prototyping a new feature, debugging a complex query, or optimizing application performance, these resources provide the knowledge and tools you need. Topics span programming language integrations, development workflows, testing strategies, debugging techniques, and operational best practices.</p> <h3 id="what-youll-find" class="position-relative d-flex align-items-center group"> <span>What You&amp;rsquo;ll Find</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="what-youll-find" aria-haspopup="dialog" aria-label="Share link: What Youll Find"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h3> <h4 id="development-tools" class="position-relative d-flex align-items-center group"> <span>Development Tools</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="development-tools" aria-haspopup="dialog" aria-label="Share link: Development Tools"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h4><p><strong>Interactive Shell (REPL)</strong></p> <ul> <li>Interactive query development with immediate feedback</li> <li>Syntax highlighting and auto-completion</li> <li>Multi-line editing for complex queries</li> <li>Transaction management and session persistence</li> <li>Query profiling and execution plan analysis</li> <li>Meta-commands for database introspection</li> <li>History search and command recall</li> <li>Result formatting and export</li> </ul> <p><strong>CLI Tools</strong></p> <ul> <li>Database server management (<code>geode serve</code>)</li> <li>Interactive shell access (<code>geode shell</code>)</li> <li>Schema management and migrations</li> <li>Backup and restore operations</li> <li>Performance monitoring and diagnostics</li> <li>Configuration management</li> <li>Deployment automation</li> <li>Testing and validation tools</li> </ul> <p><strong>Language Server Protocol (LSP)</strong></p> <ul> <li>IDE integration for VS Code, Vim, Emacs, and others</li> <li>Real-time syntax validation and error checking</li> <li>Context-aware auto-completion</li> <li>Hover documentation and tooltips</li> <li>Go-to-definition navigation</li> <li>Find references and symbols</li> <li>Code formatting and refactoring</li> <li>Schema-aware suggestions</li> </ul> <h4 id="client-libraries" class="position-relative d-flex align-items-center group"> <span>Client Libraries</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="client-libraries" aria-haspopup="dialog" aria-label="Share link: Client Libraries"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h4><p><strong>Official SDKs</strong></p> <ul> <li><strong>Go Client</strong>: <code>database/sql</code> driver with connection pooling</li> <li><strong>Python Client</strong>: Async client with aioquic and connection pooling</li> <li><strong>Rust Client</strong>: Tokio-based high-performance client</li> <li><strong>Zig Client</strong>: Native Zig implementation with vendored QUIC</li> </ul> <p><strong>Common Features</strong></p> <ul> <li>QUIC + TLS 1.3 transport protocol</li> <li>Connection pooling and management</li> <li>Prepared statement support</li> <li>Transaction management with savepoints</li> <li>Streaming result sets for large queries</li> <li>Parametrized queries for SQL injection prevention</li> <li>Error handling with GQL status codes</li> <li>Type-safe value marshaling</li> </ul> <h4 id="api-and-protocol" class="position-relative d-flex align-items-center group"> <span>API and Protocol</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="api-and-protocol" aria-haspopup="dialog" aria-label="Share link: API and Protocol"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h4><p><strong>GQL Query API</strong></p> <ul> <li>ISO/IEC 39075:2024 compliant query language</li> <li>Pattern matching with ASCII-art syntax</li> <li>CRUD operations (INSERT, UPDATE, DELETE)</li> <li>Aggregations and subqueries</li> <li>Path queries and graph algorithms</li> <li>Transaction control (BEGIN, COMMIT, ROLLBACK)</li> <li>Prepared statements and parameter binding</li> </ul> <p><strong>Wire Protocol</strong></p> <ul> <li>Protobuf wire protocol over QUIC (default) or gRPC</li> <li>Multiplexed streams for concurrent queries</li> <li>Request types: <code>HelloRequest</code>, <code>ExecuteRequest</code>, <code>PullRequest</code>, <code>BeginRequest</code>, <code>CommitRequest</code></li> <li>Response type: <code>ExecutionResponse</code> (payloads: <code>SchemaDefinition</code>, <code>DataPage</code>, <code>Error</code>, <code>ExplainPayload</code>, <code>ProfilePayload</code>)</li> <li>Streaming results with flow control</li> <li>Connection migration support</li> <li>0-RTT resumption for low latency</li> </ul> <h4 id="development-workflows" class="position-relative d-flex align-items-center group"> <span>Development Workflows</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="development-workflows" aria-haspopup="dialog" aria-label="Share link: Development Workflows"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h4><p><strong>Local Development</strong></p> <ul> <li>Quick start with Docker or binary installation</li> <li>REPL-driven query development</li> <li>Schema design and iteration</li> <li>Test data generation and seeding</li> <li>Local debugging with profiling tools</li> <li>Integration testing with testcontainers</li> </ul> <p><strong>CI/CD Integration</strong></p> <ul> <li>Automated testing in CI pipelines</li> <li>Schema migration automation</li> <li>Performance regression testing</li> <li>Deployment to staging and production</li> <li>Rollback strategies and blue-green deployments</li> <li>Monitoring and observability integration</li> </ul> <p><strong>Debugging and Profiling</strong></p> <ul> <li>EXPLAIN for query execution plans</li> <li>PROFILE for performance analysis</li> <li>Query tracing and logging</li> <li>Connection debugging</li> <li>Performance bottleneck identification</li> <li>Memory and CPU profiling</li> </ul> <h3 id="use-cases-with-code-examples" class="position-relative d-flex align-items-center group"> <span>Use Cases with Code Examples</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="use-cases-with-code-examples" aria-haspopup="dialog" aria-label="Share link: Use Cases with Code Examples"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h3> <h4 id="rapid-prototyping-with-repl" class="position-relative d-flex align-items-center group"> <span>Rapid Prototyping with REPL</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="rapid-prototyping-with-repl" aria-haspopup="dialog" aria-label="Share link: Rapid Prototyping with REPL"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h4><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># Start interactive shell</span> </span></span><span class="line"><span class="cl">geode shell </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="c1"># Explore existing data</span> </span></span><span class="line"><span class="cl">geode&gt; MATCH <span class="o">(</span>n<span class="o">)</span> RETURN DISTINCT labels<span class="o">(</span>n<span class="o">)</span>, count<span class="o">(</span>*<span class="o">)</span><span class="p">;</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="c1"># Test query patterns</span> </span></span><span class="line"><span class="cl">geode&gt; MATCH <span class="o">(</span>p:Person<span class="o">)</span>-<span class="o">[</span>:KNOWS<span class="o">]</span>-&gt;<span class="o">(</span>f:Person<span class="o">)</span> </span></span><span class="line"><span class="cl"> WHERE p.age &gt; <span class="m">30</span> </span></span><span class="line"><span class="cl"> RETURN p.name, collect<span class="o">(</span>f.name<span class="o">)</span> AS friends<span class="p">;</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="c1"># Profile for performance</span> </span></span><span class="line"><span class="cl">geode&gt; <span class="se">\p</span>rofile MATCH <span class="o">(</span>p:Person<span class="o">)</span>-<span class="o">[</span>:KNOWS*2<span class="o">]</span>-<span class="o">(</span>friend<span class="o">)</span> </span></span><span class="line"><span class="cl"> WHERE p.name <span class="o">=</span> <span class="s1">&#39;Alice&#39;</span> </span></span><span class="line"><span class="cl"> RETURN DISTINCT friend.name<span class="p">;</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="c1"># Save successful queries</span> </span></span><span class="line"><span class="cl">geode&gt; <span class="se">\s</span>ave queries/social_network.gql </span></span></code></pre></div> <h4 id="building-applications-with-client-libraries" class="position-relative d-flex align-items-center group"> <span>Building Applications with Client Libraries</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="building-applications-with-client-libraries" aria-haspopup="dialog" aria-label="Share link: Building Applications with Client Libraries"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h4><p><strong>Python Example</strong></p> <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">geode_client</span> </span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">asyncio</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="k">async</span> <span class="k">def</span> <span class="nf">get_user_recommendations</span><span class="p">(</span><span class="n">user_id</span><span class="p">:</span> <span class="nb">int</span><span class="p">,</span> <span class="n">limit</span><span class="p">:</span> <span class="nb">int</span> <span class="o">=</span> <span class="mi">10</span><span class="p">):</span> </span></span><span class="line"><span class="cl"> <span class="s2">&#34;&#34;&#34;Get product recommendations for a user.&#34;&#34;&#34;</span> </span></span><span class="line"><span class="cl"> <span class="n">client</span> <span class="o">=</span> <span class="n">geode_client</span><span class="o">.</span><span class="n">open_database</span><span class="p">(</span><span class="s1">&#39;quic://localhost:3141&#39;</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="k">async</span> <span class="k">with</span> <span class="n">client</span><span class="o">.</span><span class="n">connection</span><span class="p">()</span> <span class="k">as</span> <span class="n">conn</span><span class="p">:</span> </span></span><span class="line"><span class="cl"> <span class="n">query</span> <span class="o">=</span> <span class="s2">&#34;&#34;&#34; </span></span></span><span class="line"><span class="cl"><span class="s2"> MATCH (user:User {id: $user_id})-[:PURCHASED]-&gt;(product:Product) </span></span></span><span class="line"><span class="cl"><span class="s2"> &lt;-[:PURCHASED]-(similar:User)-[:PURCHASED]-&gt;(rec:Product) </span></span></span><span class="line"><span class="cl"><span class="s2"> WHERE NOT EXISTS { </span></span></span><span class="line"><span class="cl"><span class="s2"> MATCH (user)-[:PURCHASED]-&gt;(rec) </span></span></span><span class="line"><span class="cl"><span class="s2"> } </span></span></span><span class="line"><span class="cl"><span class="s2"> RETURN rec.name AS product, </span></span></span><span class="line"><span class="cl"><span class="s2"> rec.price AS price, </span></span></span><span class="line"><span class="cl"><span class="s2"> COUNT(similar) AS score </span></span></span><span class="line"><span class="cl"><span class="s2"> ORDER BY score DESC, rec.rating DESC </span></span></span><span class="line"><span class="cl"><span class="s2"> LIMIT $limit </span></span></span><span class="line"><span class="cl"><span class="s2"> &#34;&#34;&#34;</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="n">result</span><span class="p">,</span> <span class="n">_</span> <span class="o">=</span> <span class="k">await</span> <span class="n">conn</span><span class="o">.</span><span class="n">query</span><span class="p">(</span><span class="n">query</span><span class="p">,</span> <span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="s1">&#39;user_id&#39;</span><span class="p">:</span> <span class="n">user_id</span><span class="p">,</span> </span></span><span class="line"><span class="cl"> <span class="s1">&#39;limit&#39;</span><span class="p">:</span> <span class="n">limit</span> </span></span><span class="line"><span class="cl"> <span class="p">})</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="n">recommendations</span> <span class="o">=</span> <span class="p">[]</span> </span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">row</span> <span class="ow">in</span> <span class="n">result</span><span class="o">.</span><span class="n">rows</span><span class="p">:</span> </span></span><span class="line"><span class="cl"> <span class="n">recommendations</span><span class="o">.</span><span class="n">append</span><span class="p">({</span> </span></span><span class="line"><span class="cl"> <span class="s1">&#39;product&#39;</span><span class="p">:</span> <span class="n">row</span><span class="p">[</span><span class="s1">&#39;product&#39;</span><span class="p">],</span> </span></span><span class="line"><span class="cl"> <span class="s1">&#39;price&#39;</span><span class="p">:</span> <span class="n">row</span><span class="p">[</span><span class="s1">&#39;price&#39;</span><span class="p">],</span> </span></span><span class="line"><span class="cl"> <span class="s1">&#39;score&#39;</span><span class="p">:</span> <span class="n">row</span><span class="p">[</span><span class="s1">&#39;score&#39;</span><span class="p">]</span> </span></span><span class="line"><span class="cl"> <span class="p">})</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">recommendations</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="c1"># Use in application</span> </span></span><span class="line"><span class="cl"><span class="n">recommendations</span> <span class="o">=</span> <span class="n">asyncio</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="n">get_user_recommendations</span><span class="p">(</span><span class="mi">12345</span><span class="p">))</span> </span></span><span class="line"><span class="cl"><span class="k">for</span> <span class="n">rec</span> <span class="ow">in</span> <span class="n">recommendations</span><span class="p">:</span> </span></span><span class="line"><span class="cl"> <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;</span><span class="si">{</span><span class="n">rec</span><span class="p">[</span><span class="s1">&#39;product&#39;</span><span class="p">]</span><span class="si">}</span><span class="s2">: $</span><span class="si">{</span><span class="n">rec</span><span class="p">[</span><span class="s1">&#39;price&#39;</span><span class="p">]</span><span class="si">}</span><span class="s2"> (score: </span><span class="si">{</span><span class="n">rec</span><span class="p">[</span><span class="s1">&#39;score&#39;</span><span class="p">]</span><span class="si">}</span><span class="s2">)&#34;</span><span class="p">)</span> </span></span></code></pre></div><p><strong>Go Example</strong></p> <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kn">package</span> <span class="nx">main</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="p">(</span> </span></span><span class="line"><span class="cl"> <span class="s">&#34;context&#34;</span> </span></span><span class="line"><span class="cl"> <span class="s">&#34;database/sql&#34;</span> </span></span><span class="line"><span class="cl"> <span class="s">&#34;log&#34;</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="nx">_</span> <span class="s">&#34;geodedb.com/geode&#34;</span> </span></span><span class="line"><span class="cl"><span class="p">)</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="kd">type</span> <span class="nx">Product</span> <span class="kd">struct</span> <span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">Name</span> <span class="kt">string</span> </span></span><span class="line"><span class="cl"> <span class="nx">Price</span> <span class="kt">float64</span> </span></span><span class="line"><span class="cl"> <span class="nx">Score</span> <span class="kt">int</span> </span></span><span class="line"><span class="cl"><span class="p">}</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="kd">func</span> <span class="nf">GetRecommendations</span><span class="p">(</span><span class="nx">userID</span> <span class="kt">int</span><span class="p">,</span> <span class="nx">limit</span> <span class="kt">int</span><span class="p">)</span> <span class="p">([]</span><span class="nx">Product</span><span class="p">,</span> <span class="kt">error</span><span class="p">)</span> <span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">db</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">sql</span><span class="p">.</span><span class="nf">Open</span><span class="p">(</span><span class="s">&#34;geode&#34;</span><span class="p">,</span> <span class="s">&#34;quic://localhost:3141&#34;</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="kc">nil</span><span class="p">,</span> <span class="nx">err</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="k">defer</span> <span class="nx">db</span><span class="p">.</span><span class="nf">Close</span><span class="p">()</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="nx">query</span> <span class="o">:=</span> <span class="s">` </span></span></span><span class="line"><span class="cl"><span class="s"> MATCH (user:User {id: $1})-[:PURCHASED]-&gt;(product:Product) </span></span></span><span class="line"><span class="cl"><span class="s"> &lt;-[:PURCHASED]-(similar:User)-[:PURCHASED]-&gt;(rec:Product) </span></span></span><span class="line"><span class="cl"><span class="s"> WHERE NOT EXISTS { </span></span></span><span class="line"><span class="cl"><span class="s"> MATCH (user)-[:PURCHASED]-&gt;(rec) </span></span></span><span class="line"><span class="cl"><span class="s"> } </span></span></span><span class="line"><span class="cl"><span class="s"> RETURN rec.name, rec.price, COUNT(similar) AS score </span></span></span><span class="line"><span class="cl"><span class="s"> ORDER BY score DESC, rec.rating DESC </span></span></span><span class="line"><span class="cl"><span class="s"> LIMIT $2 </span></span></span><span class="line"><span class="cl"><span class="s"> `</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="nx">rows</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">db</span><span class="p">.</span><span class="nf">QueryContext</span><span class="p">(</span><span class="nx">context</span><span class="p">.</span><span class="nf">Background</span><span class="p">(),</span> <span class="nx">query</span><span class="p">,</span> <span class="nx">userID</span><span class="p">,</span> <span class="nx">limit</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="kc">nil</span><span class="p">,</span> <span class="nx">err</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="k">defer</span> <span class="nx">rows</span><span class="p">.</span><span class="nf">Close</span><span class="p">()</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">products</span> <span class="p">[]</span><span class="nx">Product</span> </span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nx">rows</span><span class="p">.</span><span class="nf">Next</span><span class="p">()</span> <span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">p</span> <span class="nx">Product</span> </span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">rows</span><span class="p">.</span><span class="nf">Scan</span><span class="p">(</span><span class="o">&amp;</span><span class="nx">p</span><span class="p">.</span><span class="nx">Name</span><span class="p">,</span> <span class="o">&amp;</span><span class="nx">p</span><span class="p">.</span><span class="nx">Price</span><span class="p">,</span> <span class="o">&amp;</span><span class="nx">p</span><span class="p">.</span><span class="nx">Score</span><span class="p">);</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="kc">nil</span><span class="p">,</span> <span class="nx">err</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="nx">products</span> <span class="p">=</span> <span class="nb">append</span><span class="p">(</span><span class="nx">products</span><span class="p">,</span> <span class="nx">p</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nx">products</span><span class="p">,</span> <span class="nx">rows</span><span class="p">.</span><span class="nf">Err</span><span class="p">()</span> </span></span><span class="line"><span class="cl"><span class="p">}</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">recommendations</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nf">GetRecommendations</span><span class="p">(</span><span class="mi">12345</span><span class="p">,</span> <span class="mi">10</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">log</span><span class="p">.</span><span class="nf">Fatal</span><span class="p">(</span><span class="nx">err</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nx">_</span><span class="p">,</span> <span class="nx">rec</span> <span class="o">:=</span> <span class="k">range</span> <span class="nx">recommendations</span> <span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">log</span><span class="p">.</span><span class="nf">Printf</span><span class="p">(</span><span class="s">&#34;%s: $%.2f (score: %d)&#34;</span><span class="p">,</span> <span class="nx">rec</span><span class="p">.</span><span class="nx">Name</span><span class="p">,</span> <span class="nx">rec</span><span class="p">.</span><span class="nx">Price</span><span class="p">,</span> <span class="nx">rec</span><span class="p">.</span><span class="nx">Score</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"><span class="p">}</span> </span></span></code></pre></div> <h4 id="ide-integration-with-lsp" class="position-relative d-flex align-items-center group"> <span>IDE Integration with LSP</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="ide-integration-with-lsp" aria-haspopup="dialog" aria-label="Share link: IDE Integration with LSP"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h4><p><strong>VS Code Configuration</strong></p> <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nt">&#34;gql.server.host&#34;</span><span class="p">:</span> <span class="s2">&#34;localhost&#34;</span><span class="p">,</span> </span></span><span class="line"><span class="cl"> <span class="nt">&#34;gql.server.port&#34;</span><span class="p">:</span> <span class="mi">3141</span><span class="p">,</span> </span></span><span class="line"><span class="cl"> <span class="nt">&#34;gql.validation.enabled&#34;</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span> </span></span><span class="line"><span class="cl"> <span class="nt">&#34;gql.completion.autoComplete&#34;</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span> </span></span><span class="line"><span class="cl"> <span class="nt">&#34;gql.format.enable&#34;</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span> </span></span><span class="line"><span class="cl"> <span class="nt">&#34;gql.hover.documentation&#34;</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span> </span></span><span class="line"><span class="cl"> <span class="nt">&#34;editor.formatOnSave&#34;</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span> </span></span><span class="line"><span class="cl"> <span class="nt">&#34;files.associations&#34;</span><span class="p">:</span> <span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nt">&#34;*.gql&#34;</span><span class="p">:</span> <span class="s2">&#34;gql&#34;</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"><span class="p">}</span> </span></span></code></pre></div><p><strong>Query Development with LSP</strong></p> <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-gql" data-lang="gql"><span class="line"><span class="cl"><span class="err">--</span><span class="w"> </span><span class="py">Full</span><span class="w"> </span><span class="py">IDE</span><span class="w"> </span><span class="py">support</span><span class="p">:</span><span class="w"> </span><span class="nc">auto</span><span class="err">-</span><span class="py">completion</span><span class="p">,</span><span class="w"> </span><span class="py">error</span><span class="w"> </span><span class="py">checking</span><span class="p">,</span><span class="w"> </span><span class="py">go</span><span class="err">-</span><span class="py">to</span><span class="err">-</span><span class="py">definition</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">MATCH</span><span class="w"> </span><span class="p">(</span><span class="py">p</span><span class="p">:</span><span class="nc">Person</span><span class="p">)</span><span class="err">-</span><span class="p">[:</span><span class="nc">WORKS_AT</span><span class="p">]</span><span class="err">-&gt;</span><span class="p">(</span><span class="py">c</span><span class="p">:</span><span class="nc">Company</span><span class="p">)</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">WHERE</span><span class="w"> </span><span class="py">p</span><span class="err">.</span><span class="py">age</span><span class="w"> </span><span class="err">&gt;</span><span class="w"> </span><span class="nv">$minAge</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">AND</span><span class="w"> </span><span class="py">c</span><span class="err">.</span><span class="py">industry</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="nv">$industry</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">RETURN</span><span class="w"> </span><span class="py">p</span><span class="err">.</span><span class="py">name</span><span class="w"> </span><span class="py">AS</span><span class="w"> </span><span class="py">employee</span><span class="p">,</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">c</span><span class="err">.</span><span class="py">name</span><span class="w"> </span><span class="py">AS</span><span class="w"> </span><span class="py">company</span><span class="p">,</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="py">p</span><span class="err">.</span><span class="py">salary</span><span class="w"> </span><span class="py">AS</span><span class="w"> </span><span class="py">salary</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">ORDER</span><span class="w"> </span><span class="py">BY</span><span class="w"> </span><span class="py">p</span><span class="err">.</span><span class="py">salary</span><span class="w"> </span><span class="py">DESC</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="py">LIMIT</span><span class="w"> </span><span class="nv">$limit</span><span class="w"> </span></span></span></code></pre></div> <h4 id="automated-testing" class="position-relative d-flex align-items-center group"> <span>Automated Testing</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="automated-testing" aria-haspopup="dialog" aria-label="Share link: Automated Testing"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h4><p><strong>Python Testing Example</strong></p> <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">pytest</span> </span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">geode_client</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="nd">@pytest.fixture</span> </span></span><span class="line"><span class="cl"><span class="k">async</span> <span class="k">def</span> <span class="nf">db</span><span class="p">():</span> </span></span><span class="line"><span class="cl"> <span class="s2">&#34;&#34;&#34;Provide test database connection.&#34;&#34;&#34;</span> </span></span><span class="line"><span class="cl"> <span class="n">client</span> <span class="o">=</span> <span class="n">geode_client</span><span class="o">.</span><span class="n">open_database</span><span class="p">(</span><span class="s1">&#39;quic://localhost:3141&#39;</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="k">async</span> <span class="k">with</span> <span class="n">client</span><span class="o">.</span><span class="n">connection</span><span class="p">()</span> <span class="k">as</span> <span class="n">conn</span><span class="p">:</span> </span></span><span class="line"><span class="cl"> <span class="c1"># Setup: Create test data</span> </span></span><span class="line"><span class="cl"> <span class="k">await</span> <span class="n">conn</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="s2">&#34;&#34;&#34; </span></span></span><span class="line"><span class="cl"><span class="s2"> INSERT (:Person {id: 1, name: &#39;Alice&#39;, age: 30}), </span></span></span><span class="line"><span class="cl"><span class="s2"> (:Person {id: 2, name: &#39;Bob&#39;, age: 25}), </span></span></span><span class="line"><span class="cl"><span class="s2"> (:Person </span><span class="si">{id: 1}</span><span class="s2">)-[:KNOWS]-&gt;(:Person </span><span class="si">{id: 2}</span><span class="s2">) </span></span></span><span class="line"><span class="cl"><span class="s2"> &#34;&#34;&#34;</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="k">yield</span> <span class="n">conn</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="c1"># Teardown: Clean up test data</span> </span></span><span class="line"><span class="cl"> <span class="k">await</span> <span class="n">conn</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="s2">&#34;MATCH (n:Person) DELETE n&#34;</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="nd">@pytest.mark.asyncio</span> </span></span><span class="line"><span class="cl"><span class="k">async</span> <span class="k">def</span> <span class="nf">test_friend_recommendation</span><span class="p">(</span><span class="n">db</span><span class="p">):</span> </span></span><span class="line"><span class="cl"> <span class="s2">&#34;&#34;&#34;Test friend recommendation query.&#34;&#34;&#34;</span> </span></span><span class="line"><span class="cl"> <span class="n">result</span><span class="p">,</span> <span class="n">_</span> <span class="o">=</span> <span class="k">await</span> <span class="n">db</span><span class="o">.</span><span class="n">query</span><span class="p">(</span><span class="s2">&#34;&#34;&#34; </span></span></span><span class="line"><span class="cl"><span class="s2"> MATCH (p:Person </span><span class="si">{id: 1}</span><span class="s2">)-[:KNOWS]-&gt;()-[:KNOWS]-&gt;(foaf:Person) </span></span></span><span class="line"><span class="cl"><span class="s2"> WHERE NOT EXISTS { </span></span></span><span class="line"><span class="cl"><span class="s2"> MATCH (p)-[:KNOWS]-&gt;(foaf) </span></span></span><span class="line"><span class="cl"><span class="s2"> } </span></span></span><span class="line"><span class="cl"><span class="s2"> RETURN foaf.name AS recommended_friend </span></span></span><span class="line"><span class="cl"><span class="s2"> &#34;&#34;&#34;</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="n">friends</span> <span class="o">=</span> <span class="p">[</span><span class="n">row</span><span class="p">[</span><span class="s1">&#39;recommended_friend&#39;</span><span class="p">]</span> <span class="k">for</span> <span class="n">row</span> <span class="ow">in</span> <span class="n">result</span><span class="o">.</span><span class="n">rows</span><span class="p">]</span> </span></span><span class="line"><span class="cl"> <span class="k">assert</span> <span class="nb">len</span><span class="p">(</span><span class="n">friends</span><span class="p">)</span> <span class="o">&gt;</span> <span class="mi">0</span> </span></span></code></pre></div> <h3 id="best-practices" class="position-relative d-flex align-items-center group"> <span>Best Practices</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="best-practices" aria-haspopup="dialog" aria-label="Share link: Best Practices"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h3> <h4 id="development-workflow" class="position-relative d-flex align-items-center group"> <span>Development Workflow</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="development-workflow" aria-haspopup="dialog" aria-label="Share link: Development Workflow"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h4><ol> <li><strong>REPL-First Development</strong>: Use REPL for query prototyping</li> <li><strong>Version Control</strong>: Track queries and schema in Git</li> <li><strong>Schema Migrations</strong>: Use versioned migration scripts</li> <li><strong>Environment Parity</strong>: Keep dev/staging/prod schemas aligned</li> <li><strong>Code Reviews</strong>: Review GQL queries like application code</li> </ol> <h4 id="api-usage" class="position-relative d-flex align-items-center group"> <span>API Usage</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="api-usage" aria-haspopup="dialog" aria-label="Share link: API Usage"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h4><ol> <li><strong>Connection Pooling</strong>: Reuse connections for better performance</li> <li><strong>Prepared Statements</strong>: Use parameterized queries for security</li> <li><strong>Error Handling</strong>: Catch and handle GQL-specific errors</li> <li><strong>Transaction Boundaries</strong>: Keep transactions short and focused</li> <li><strong>Result Streaming</strong>: Stream large result sets to conserve memory</li> </ol> <h4 id="testing-strategy" class="position-relative d-flex align-items-center group"> <span>Testing Strategy</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="testing-strategy" aria-haspopup="dialog" aria-label="Share link: Testing Strategy"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h4><ol> <li><strong>Unit Tests</strong>: Test query logic with test data</li> <li><strong>Integration Tests</strong>: Test against real database</li> <li><strong>Performance Tests</strong>: Benchmark critical queries</li> <li><strong>Schema Tests</strong>: Validate schema integrity</li> <li><strong>Regression Tests</strong>: Prevent performance regressions</li> </ol> <h4 id="debugging-techniques" class="position-relative d-flex align-items-center group"> <span>Debugging Techniques</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="debugging-techniques" aria-haspopup="dialog" aria-label="Share link: Debugging Techniques"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h4><ol> <li><strong>EXPLAIN Queries</strong>: Understand execution plans</li> <li><strong>PROFILE Queries</strong>: Measure actual performance</li> <li><strong>Logging</strong>: Enable query logging in development</li> <li><strong>Tracing</strong>: Use distributed tracing for debugging</li> <li><strong>Monitoring</strong>: Watch query metrics in production</li> </ol> <h3 id="related-categories" class="position-relative d-flex align-items-center group"> <span>Related Categories</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="related-categories" aria-haspopup="dialog" aria-label="Share link: Related Categories"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h3><ul> <li><a href="/categories/tutorials/" >Tutorials</a> - Step-by-step learning guides</li> <li><a href="/categories/query-language/" >Query Language</a> - GQL reference and examples</li> <li><a href="/categories/client-libraries/" >Client Libraries</a> - SDK documentation</li> <li><a href="/categories/reference/" >Reference</a> - API and protocol reference</li> <li><a href="/categories/best-practices/" >Best Practices</a> - Development guidelines</li> </ul> <h3 id="related-tags" class="position-relative d-flex align-items-center group"> <span>Related Tags</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="related-tags" aria-haspopup="dialog" aria-label="Share link: Related Tags"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h3><ul> <li><a href="/tags/repl/" >REPL</a> - Interactive shell</li> <li><a href="/tags/cli/" >CLI</a> - Command-line tools</li> <li><a href="/tags/lsp/" >LSP</a> - Language Server Protocol</li> <li><a href="/tags/api/" >API</a> - API documentation</li> <li><a href="/tags/gql/" >GQL</a> - Graph Query Language</li> <li><a href="/tags/tools/" >Tools</a> - Development tooling</li> <li><a href="/tags/debugging/" >Debugging</a> - Debugging techniques</li> <li><a href="/tags/testing/" >Testing</a> - Testing strategies</li> </ul> <h3 id="advanced-development-patterns" class="position-relative d-flex align-items-center group"> <span>Advanced Development Patterns</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="advanced-development-patterns" aria-haspopup="dialog" aria-label="Share link: Advanced Development Patterns"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h3> <h4 id="connection-pool-management" class="position-relative d-flex align-items-center group"> <span>Connection Pool Management</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="connection-pool-management" aria-haspopup="dialog" aria-label="Share link: Connection Pool Management"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h4><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">geode_client</span> </span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">contextlib</span> <span class="kn">import</span> <span class="n">asynccontextmanager</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">DatabasePool</span><span class="p">:</span> </span></span><span class="line"><span class="cl"> <span class="s2">&#34;&#34;&#34;Production-ready connection pool.&#34;&#34;&#34;</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">url</span><span class="p">,</span> <span class="n">min_size</span><span class="o">=</span><span class="mi">5</span><span class="p">,</span> <span class="n">max_size</span><span class="o">=</span><span class="mi">20</span><span class="p">):</span> </span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">url</span> <span class="o">=</span> <span class="n">url</span> </span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">min_size</span> <span class="o">=</span> <span class="n">min_size</span> </span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">max_size</span> <span class="o">=</span> <span class="n">max_size</span> </span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">_pool</span> <span class="o">=</span> <span class="kc">None</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="k">async</span> <span class="k">def</span> <span class="nf">initialize</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> </span></span><span class="line"><span class="cl"> <span class="s2">&#34;&#34;&#34;Initialize connection pool.&#34;&#34;&#34;</span> </span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">_pool</span> <span class="o">=</span> <span class="k">await</span> <span class="n">geode_client</span><span class="o">.</span><span class="n">create_pool</span><span class="p">(</span> </span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">url</span><span class="p">,</span> </span></span><span class="line"><span class="cl"> <span class="n">min_size</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">min_size</span><span class="p">,</span> </span></span><span class="line"><span class="cl"> <span class="n">max_size</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">max_size</span><span class="p">,</span> </span></span><span class="line"><span class="cl"> <span class="n">timeout</span><span class="o">=</span><span class="mi">30</span><span class="p">,</span> </span></span><span class="line"><span class="cl"> <span class="n">idle_timeout</span><span class="o">=</span><span class="mi">300</span> </span></span><span class="line"><span class="cl"> <span class="p">)</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="nd">@asynccontextmanager</span> </span></span><span class="line"><span class="cl"> <span class="k">async</span> <span class="k">def</span> <span class="nf">acquire</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> </span></span><span class="line"><span class="cl"> <span class="s2">&#34;&#34;&#34;Acquire connection from pool.&#34;&#34;&#34;</span> </span></span><span class="line"><span class="cl"> <span class="k">async</span> <span class="k">with</span> <span class="bp">self</span><span class="o">.</span><span class="n">_pool</span><span class="o">.</span><span class="n">acquire</span><span class="p">()</span> <span class="k">as</span> <span class="n">conn</span><span class="p">:</span> </span></span><span class="line"><span class="cl"> <span class="k">try</span><span class="p">:</span> </span></span><span class="line"><span class="cl"> <span class="k">yield</span> <span class="n">conn</span> </span></span><span class="line"><span class="cl"> <span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span> </span></span><span class="line"><span class="cl"> <span class="c1"># Log error with context</span> </span></span><span class="line"><span class="cl"> <span class="n">logger</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;Database error: </span><span class="si">{</span><span class="n">e</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">,</span> <span class="n">exc_info</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="k">raise</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="k">async</span> <span class="k">def</span> <span class="nf">close</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> </span></span><span class="line"><span class="cl"> <span class="s2">&#34;&#34;&#34;Close all pool connections.&#34;&#34;&#34;</span> </span></span><span class="line"><span class="cl"> <span class="k">await</span> <span class="bp">self</span><span class="o">.</span><span class="n">_pool</span><span class="o">.</span><span class="n">close</span><span class="p">()</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="c1"># Usage</span> </span></span><span class="line"><span class="cl"><span class="n">pool</span> <span class="o">=</span> <span class="n">DatabasePool</span><span class="p">(</span><span class="s2">&#34;quic://localhost:3141&#34;</span><span class="p">)</span> </span></span><span class="line"><span class="cl"><span class="k">await</span> <span class="n">pool</span><span class="o">.</span><span class="n">initialize</span><span class="p">()</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="k">async</span> <span class="k">with</span> <span class="n">pool</span><span class="o">.</span><span class="n">acquire</span><span class="p">()</span> <span class="k">as</span> <span class="n">conn</span><span class="p">:</span> </span></span><span class="line"><span class="cl"> <span class="n">result</span><span class="p">,</span> <span class="n">_</span> <span class="o">=</span> <span class="k">await</span> <span class="n">conn</span><span class="o">.</span><span class="n">query</span><span class="p">(</span><span class="s2">&#34;MATCH (n) RETURN count(n)&#34;</span><span class="p">)</span> </span></span></code></pre></div> <h4 id="query-builder-pattern" class="position-relative d-flex align-items-center group"> <span>Query Builder Pattern</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="query-builder-pattern" aria-haspopup="dialog" aria-label="Share link: Query Builder Pattern"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h4><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">GQLQueryBuilder</span><span class="p">:</span> </span></span><span class="line"><span class="cl"> <span class="s2">&#34;&#34;&#34;Fluent API for building GQL queries.&#34;&#34;&#34;</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> </span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">match_clauses</span> <span class="o">=</span> <span class="p">[]</span> </span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">where_conditions</span> <span class="o">=</span> <span class="p">[]</span> </span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">return_expressions</span> <span class="o">=</span> <span class="p">[]</span> </span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">order_by</span> <span class="o">=</span> <span class="p">[]</span> </span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">limit_value</span> <span class="o">=</span> <span class="kc">None</span> </span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">params</span> <span class="o">=</span> <span class="p">{}</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">match</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">pattern</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span> </span></span><span class="line"><span class="cl"> <span class="s2">&#34;&#34;&#34;Add MATCH clause.&#34;&#34;&#34;</span> </span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">match_clauses</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">pattern</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">params</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">kwargs</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="bp">self</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">where</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">condition</span><span class="p">):</span> </span></span><span class="line"><span class="cl"> <span class="s2">&#34;&#34;&#34;Add WHERE condition.&#34;&#34;&#34;</span> </span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">where_conditions</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">condition</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="bp">self</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">return_</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="n">expressions</span><span class="p">):</span> </span></span><span class="line"><span class="cl"> <span class="s2">&#34;&#34;&#34;Add RETURN expressions.&#34;&#34;&#34;</span> </span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">return_expressions</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">expressions</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="bp">self</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">order_by_desc</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">field</span><span class="p">):</span> </span></span><span class="line"><span class="cl"> <span class="s2">&#34;&#34;&#34;Add ORDER BY DESC.&#34;&#34;&#34;</span> </span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">order_by</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;</span><span class="si">{</span><span class="n">field</span><span class="si">}</span><span class="s2"> DESC&#34;</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="bp">self</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">limit</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">count</span><span class="p">):</span> </span></span><span class="line"><span class="cl"> <span class="s2">&#34;&#34;&#34;Add LIMIT.&#34;&#34;&#34;</span> </span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">limit_value</span> <span class="o">=</span> <span class="n">count</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="bp">self</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">build</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> </span></span><span class="line"><span class="cl"> <span class="s2">&#34;&#34;&#34;Build final query string.&#34;&#34;&#34;</span> </span></span><span class="line"><span class="cl"> <span class="n">parts</span> <span class="o">=</span> <span class="p">[]</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="c1"># MATCH</span> </span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">clause</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">match_clauses</span><span class="p">:</span> </span></span><span class="line"><span class="cl"> <span class="n">parts</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;MATCH </span><span class="si">{</span><span class="n">clause</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="c1"># WHERE</span> </span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">where_conditions</span><span class="p">:</span> </span></span><span class="line"><span class="cl"> <span class="n">parts</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s2">&#34;WHERE &#34;</span> <span class="o">+</span> <span class="s2">&#34; AND &#34;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">where_conditions</span><span class="p">))</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="c1"># RETURN</span> </span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">return_expressions</span><span class="p">:</span> </span></span><span class="line"><span class="cl"> <span class="n">parts</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s2">&#34;RETURN &#34;</span> <span class="o">+</span> <span class="s2">&#34;, &#34;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">return_expressions</span><span class="p">))</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="c1"># ORDER BY</span> </span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">order_by</span><span class="p">:</span> </span></span><span class="line"><span class="cl"> <span class="n">parts</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s2">&#34;ORDER BY &#34;</span> <span class="o">+</span> <span class="s2">&#34;, &#34;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">order_by</span><span class="p">))</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="c1"># LIMIT</span> </span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">limit_value</span><span class="p">:</span> </span></span><span class="line"><span class="cl"> <span class="n">parts</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;LIMIT </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">limit_value</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="s2">&#34;</span><span class="se">\n</span><span class="s2">&#34;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">parts</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="c1"># Usage</span> </span></span><span class="line"><span class="cl"><span class="n">query</span> <span class="o">=</span> <span class="p">(</span><span class="n">GQLQueryBuilder</span><span class="p">()</span> </span></span><span class="line"><span class="cl"> <span class="o">.</span><span class="k">match</span><span class="p">(</span><span class="s2">&#34;(u:User)-[:POSTED]-&gt;(p:Post)&#34;</span><span class="p">,</span> <span class="n">user_id</span><span class="o">=</span><span class="mi">123</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="o">.</span><span class="n">where</span><span class="p">(</span><span class="s2">&#34;u.id = $user_id&#34;</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="o">.</span><span class="n">where</span><span class="p">(</span><span class="s2">&#34;p.created &gt; $min_date&#34;</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="o">.</span><span class="n">return_</span><span class="p">(</span><span class="s2">&#34;p.title&#34;</span><span class="p">,</span> <span class="s2">&#34;p.created&#34;</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="o">.</span><span class="n">order_by_desc</span><span class="p">(</span><span class="s2">&#34;p.created&#34;</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="o">.</span><span class="n">limit</span><span class="p">(</span><span class="mi">10</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="o">.</span><span class="n">build</span><span class="p">())</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">query</span><span class="p">)</span> </span></span><span class="line"><span class="cl"><span class="c1"># Output:</span> </span></span><span class="line"><span class="cl"><span class="c1"># MATCH (u:User)-[:POSTED]-&gt;(p:Post)</span> </span></span><span class="line"><span class="cl"><span class="c1"># WHERE u.id = $user_id AND p.created &gt; $min_date</span> </span></span><span class="line"><span class="cl"><span class="c1"># RETURN p.title, p.created</span> </span></span><span class="line"><span class="cl"><span class="c1"># ORDER BY p.created DESC</span> </span></span><span class="line"><span class="cl"><span class="c1"># LIMIT 10</span> </span></span></code></pre></div> <h4 id="repository-pattern" class="position-relative d-flex align-items-center group"> <span>Repository Pattern</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="repository-pattern" aria-haspopup="dialog" aria-label="Share link: Repository Pattern"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h4><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">abc</span> <span class="kn">import</span> <span class="n">ABC</span><span class="p">,</span> <span class="n">abstractmethod</span> </span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">Optional</span><span class="p">,</span> <span class="n">List</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Repository</span><span class="p">(</span><span class="n">ABC</span><span class="p">):</span> </span></span><span class="line"><span class="cl"> <span class="s2">&#34;&#34;&#34;Base repository interface.&#34;&#34;&#34;</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="nd">@abstractmethod</span> </span></span><span class="line"><span class="cl"> <span class="k">async</span> <span class="k">def</span> <span class="nf">find_by_id</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="nb">id</span><span class="p">:</span> <span class="nb">int</span><span class="p">):</span> </span></span><span class="line"><span class="cl"> <span class="k">pass</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="nd">@abstractmethod</span> </span></span><span class="line"><span class="cl"> <span class="k">async</span> <span class="k">def</span> <span class="nf">find_all</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">List</span><span class="p">:</span> </span></span><span class="line"><span class="cl"> <span class="k">pass</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="nd">@abstractmethod</span> </span></span><span class="line"><span class="cl"> <span class="k">async</span> <span class="k">def</span> <span class="nf">save</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">entity</span><span class="p">):</span> </span></span><span class="line"><span class="cl"> <span class="k">pass</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="nd">@abstractmethod</span> </span></span><span class="line"><span class="cl"> <span class="k">async</span> <span class="k">def</span> <span class="nf">delete</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="nb">id</span><span class="p">:</span> <span class="nb">int</span><span class="p">):</span> </span></span><span class="line"><span class="cl"> <span class="k">pass</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">UserRepository</span><span class="p">(</span><span class="n">Repository</span><span class="p">):</span> </span></span><span class="line"><span class="cl"> <span class="s2">&#34;&#34;&#34;User-specific repository implementation.&#34;&#34;&#34;</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">pool</span><span class="p">):</span> </span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">pool</span> <span class="o">=</span> <span class="n">pool</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="k">async</span> <span class="k">def</span> <span class="nf">find_by_id</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">user_id</span><span class="p">:</span> <span class="nb">int</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">dict</span><span class="p">]:</span> </span></span><span class="line"><span class="cl"> <span class="s2">&#34;&#34;&#34;Find user by ID.&#34;&#34;&#34;</span> </span></span><span class="line"><span class="cl"> <span class="k">async</span> <span class="k">with</span> <span class="bp">self</span><span class="o">.</span><span class="n">pool</span><span class="o">.</span><span class="n">acquire</span><span class="p">()</span> <span class="k">as</span> <span class="n">conn</span><span class="p">:</span> </span></span><span class="line"><span class="cl"> <span class="n">result</span><span class="p">,</span> <span class="n">_</span> <span class="o">=</span> <span class="k">await</span> <span class="n">conn</span><span class="o">.</span><span class="n">query</span><span class="p">(</span><span class="s2">&#34;&#34;&#34; </span></span></span><span class="line"><span class="cl"><span class="s2"> MATCH (u:User {id: $id}) </span></span></span><span class="line"><span class="cl"><span class="s2"> RETURN u.id AS id, </span></span></span><span class="line"><span class="cl"><span class="s2"> u.name AS name, </span></span></span><span class="line"><span class="cl"><span class="s2"> u.email AS email, </span></span></span><span class="line"><span class="cl"><span class="s2"> u.created AS created </span></span></span><span class="line"><span class="cl"><span class="s2"> &#34;&#34;&#34;</span><span class="p">,</span> <span class="p">{</span><span class="s2">&#34;id&#34;</span><span class="p">:</span> <span class="n">user_id</span><span class="p">})</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">result</span><span class="o">.</span><span class="n">rows</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">if</span> <span class="n">result</span><span class="o">.</span><span class="n">rows</span> <span class="k">else</span> <span class="kc">None</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="k">async</span> <span class="k">def</span> <span class="nf">find_by_email</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">email</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">dict</span><span class="p">]:</span> </span></span><span class="line"><span class="cl"> <span class="s2">&#34;&#34;&#34;Find user by email.&#34;&#34;&#34;</span> </span></span><span class="line"><span class="cl"> <span class="k">async</span> <span class="k">with</span> <span class="bp">self</span><span class="o">.</span><span class="n">pool</span><span class="o">.</span><span class="n">acquire</span><span class="p">()</span> <span class="k">as</span> <span class="n">conn</span><span class="p">:</span> </span></span><span class="line"><span class="cl"> <span class="n">result</span><span class="p">,</span> <span class="n">_</span> <span class="o">=</span> <span class="k">await</span> <span class="n">conn</span><span class="o">.</span><span class="n">query</span><span class="p">(</span><span class="s2">&#34;&#34;&#34; </span></span></span><span class="line"><span class="cl"><span class="s2"> MATCH (u:User {email: $email}) </span></span></span><span class="line"><span class="cl"><span class="s2"> RETURN u.id AS id, u.name AS name, u.email AS email </span></span></span><span class="line"><span class="cl"><span class="s2"> &#34;&#34;&#34;</span><span class="p">,</span> <span class="p">{</span><span class="s2">&#34;email&#34;</span><span class="p">:</span> <span class="n">email</span><span class="p">})</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">result</span><span class="o">.</span><span class="n">rows</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">if</span> <span class="n">result</span><span class="o">.</span><span class="n">rows</span> <span class="k">else</span> <span class="kc">None</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="k">async</span> <span class="k">def</span> <span class="nf">find_all</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">List</span><span class="p">[</span><span class="nb">dict</span><span class="p">]:</span> </span></span><span class="line"><span class="cl"> <span class="s2">&#34;&#34;&#34;Get all users.&#34;&#34;&#34;</span> </span></span><span class="line"><span class="cl"> <span class="k">async</span> <span class="k">with</span> <span class="bp">self</span><span class="o">.</span><span class="n">pool</span><span class="o">.</span><span class="n">acquire</span><span class="p">()</span> <span class="k">as</span> <span class="n">conn</span><span class="p">:</span> </span></span><span class="line"><span class="cl"> <span class="n">result</span><span class="p">,</span> <span class="n">_</span> <span class="o">=</span> <span class="k">await</span> <span class="n">conn</span><span class="o">.</span><span class="n">query</span><span class="p">(</span><span class="s2">&#34;&#34;&#34; </span></span></span><span class="line"><span class="cl"><span class="s2"> MATCH (u:User) </span></span></span><span class="line"><span class="cl"><span class="s2"> RETURN u.id AS id, u.name AS name, u.email AS email </span></span></span><span class="line"><span class="cl"><span class="s2"> ORDER BY u.created DESC </span></span></span><span class="line"><span class="cl"><span class="s2"> &#34;&#34;&#34;</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="p">[</span><span class="n">row</span> <span class="k">for</span> <span class="n">row</span> <span class="ow">in</span> <span class="n">result</span><span class="o">.</span><span class="n">rows</span><span class="p">]</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="k">async</span> <span class="k">def</span> <span class="nf">save</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">user</span><span class="p">:</span> <span class="nb">dict</span><span class="p">):</span> </span></span><span class="line"><span class="cl"> <span class="s2">&#34;&#34;&#34;Create or update user.&#34;&#34;&#34;</span> </span></span><span class="line"><span class="cl"> <span class="k">async</span> <span class="k">with</span> <span class="bp">self</span><span class="o">.</span><span class="n">pool</span><span class="o">.</span><span class="n">acquire</span><span class="p">()</span> <span class="k">as</span> <span class="n">conn</span><span class="p">:</span> </span></span><span class="line"><span class="cl"> <span class="k">await</span> <span class="n">conn</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="s2">&#34;&#34;&#34; </span></span></span><span class="line"><span class="cl"><span class="s2"> MERGE (u:User {email: $email}) </span></span></span><span class="line"><span class="cl"><span class="s2"> SET u.name = $name, </span></span></span><span class="line"><span class="cl"><span class="s2"> u.updated = current_timestamp() </span></span></span><span class="line"><span class="cl"><span class="s2"> ON CREATE SET u.created = current_timestamp() </span></span></span><span class="line"><span class="cl"><span class="s2"> &#34;&#34;&#34;</span><span class="p">,</span> <span class="n">user</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="k">async</span> <span class="k">def</span> <span class="nf">delete</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">user_id</span><span class="p">:</span> <span class="nb">int</span><span class="p">):</span> </span></span><span class="line"><span class="cl"> <span class="s2">&#34;&#34;&#34;Delete user.&#34;&#34;&#34;</span> </span></span><span class="line"><span class="cl"> <span class="k">async</span> <span class="k">with</span> <span class="bp">self</span><span class="o">.</span><span class="n">pool</span><span class="o">.</span><span class="n">acquire</span><span class="p">()</span> <span class="k">as</span> <span class="n">conn</span><span class="p">:</span> </span></span><span class="line"><span class="cl"> <span class="k">await</span> <span class="n">conn</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="s2">&#34;&#34;&#34; </span></span></span><span class="line"><span class="cl"><span class="s2"> MATCH (u:User {id: $id}) </span></span></span><span class="line"><span class="cl"><span class="s2"> DETACH DELETE u </span></span></span><span class="line"><span class="cl"><span class="s2"> &#34;&#34;&#34;</span><span class="p">,</span> <span class="p">{</span><span class="s2">&#34;id&#34;</span><span class="p">:</span> <span class="n">user_id</span><span class="p">})</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="c1"># Usage</span> </span></span><span class="line"><span class="cl"><span class="n">user_repo</span> <span class="o">=</span> <span class="n">UserRepository</span><span class="p">(</span><span class="n">pool</span><span class="p">)</span> </span></span><span class="line"><span class="cl"><span class="n">user</span> <span class="o">=</span> <span class="k">await</span> <span class="n">user_repo</span><span class="o">.</span><span class="n">find_by_email</span><span class="p">(</span><span class="s2">&#34;[email protected]&#34;</span><span class="p">)</span> </span></span></code></pre></div> <h4 id="error-handling-strategies" class="position-relative d-flex align-items-center group"> <span>Error Handling Strategies</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="error-handling-strategies" aria-haspopup="dialog" aria-label="Share link: Error Handling Strategies"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h4><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">enum</span> <span class="kn">import</span> <span class="n">Enum</span> </span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">Optional</span> </span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">logging</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">GeodeErrorCode</span><span class="p">(</span><span class="n">Enum</span><span class="p">):</span> </span></span><span class="line"><span class="cl"> <span class="s2">&#34;&#34;&#34;GQL error codes.&#34;&#34;&#34;</span> </span></span><span class="line"><span class="cl"> <span class="n">CONSTRAINT_VIOLATION</span> <span class="o">=</span> <span class="s2">&#34;22000&#34;</span> </span></span><span class="line"><span class="cl"> <span class="n">QUERY_TIMEOUT</span> <span class="o">=</span> <span class="s2">&#34;57014&#34;</span> </span></span><span class="line"><span class="cl"> <span class="n">SERIALIZATION_FAILURE</span> <span class="o">=</span> <span class="s2">&#34;40001&#34;</span> </span></span><span class="line"><span class="cl"> <span class="n">DEADLOCK</span> <span class="o">=</span> <span class="s2">&#34;40P01&#34;</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">RetryableError</span><span class="p">(</span><span class="ne">Exception</span><span class="p">):</span> </span></span><span class="line"><span class="cl"> <span class="s2">&#34;&#34;&#34;Error that should trigger retry.&#34;&#34;&#34;</span> </span></span><span class="line"><span class="cl"> <span class="k">pass</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">PermanentError</span><span class="p">(</span><span class="ne">Exception</span><span class="p">):</span> </span></span><span class="line"><span class="cl"> <span class="s2">&#34;&#34;&#34;Error that should not be retried.&#34;&#34;&#34;</span> </span></span><span class="line"><span class="cl"> <span class="k">pass</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="k">async</span> <span class="k">def</span> <span class="nf">execute_with_retry</span><span class="p">(</span><span class="n">func</span><span class="p">,</span> <span class="n">max_retries</span><span class="o">=</span><span class="mi">3</span><span class="p">,</span> <span class="n">backoff_factor</span><span class="o">=</span><span class="mi">2</span><span class="p">):</span> </span></span><span class="line"><span class="cl"> <span class="s2">&#34;&#34;&#34;Execute function with exponential backoff retry.&#34;&#34;&#34;</span> </span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">attempt</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">max_retries</span><span class="p">):</span> </span></span><span class="line"><span class="cl"> <span class="k">try</span><span class="p">:</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="k">await</span> <span class="n">func</span><span class="p">()</span> </span></span><span class="line"><span class="cl"> <span class="k">except</span> <span class="n">geode_client</span><span class="o">.</span><span class="n">QueryError</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span> </span></span><span class="line"><span class="cl"> <span class="n">error_code</span> <span class="o">=</span> <span class="n">e</span><span class="o">.</span><span class="n">code</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="c1"># Check if error is retryable</span> </span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">error_code</span> <span class="ow">in</span> <span class="p">[</span><span class="n">GeodeErrorCode</span><span class="o">.</span><span class="n">SERIALIZATION_FAILURE</span><span class="o">.</span><span class="n">value</span><span class="p">,</span> </span></span><span class="line"><span class="cl"> <span class="n">GeodeErrorCode</span><span class="o">.</span><span class="n">DEADLOCK</span><span class="o">.</span><span class="n">value</span><span class="p">]:</span> </span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">attempt</span> <span class="o">&lt;</span> <span class="n">max_retries</span> <span class="o">-</span> <span class="mi">1</span><span class="p">:</span> </span></span><span class="line"><span class="cl"> <span class="n">wait_time</span> <span class="o">=</span> <span class="n">backoff_factor</span> <span class="o">**</span> <span class="n">attempt</span> </span></span><span class="line"><span class="cl"> <span class="n">logging</span><span class="o">.</span><span class="n">warning</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;Retrying after </span><span class="si">{</span><span class="n">wait_time</span><span class="si">}</span><span class="s2">s due to: </span><span class="si">{</span><span class="n">e</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="k">await</span> <span class="n">asyncio</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="n">wait_time</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="k">continue</span> </span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span> </span></span><span class="line"><span class="cl"> <span class="k">raise</span> <span class="n">RetryableError</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;Max retries exceeded: </span><span class="si">{</span><span class="n">e</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span> </span></span><span class="line"><span class="cl"> <span class="c1"># Permanent error, don&#39;t retry</span> </span></span><span class="line"><span class="cl"> <span class="k">raise</span> <span class="n">PermanentError</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;Permanent error: </span><span class="si">{</span><span class="n">e</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="c1"># Usage</span> </span></span><span class="line"><span class="cl"><span class="k">async</span> <span class="k">def</span> <span class="nf">transfer_money</span><span class="p">(</span><span class="n">from_id</span><span class="p">,</span> <span class="n">to_id</span><span class="p">,</span> <span class="n">amount</span><span class="p">):</span> </span></span><span class="line"><span class="cl"> <span class="k">async</span> <span class="k">with</span> <span class="n">pool</span><span class="o">.</span><span class="n">acquire</span><span class="p">()</span> <span class="k">as</span> <span class="n">conn</span><span class="p">:</span> </span></span><span class="line"><span class="cl"> <span class="k">async</span> <span class="k">with</span> <span class="n">conn</span><span class="o">.</span><span class="n">connection</span><span class="p">()</span> <span class="k">as</span> <span class="n">tx</span><span class="p">:</span> </span></span><span class="line"><span class="cl"> <span class="k">await</span> <span class="n">tx</span><span class="o">.</span><span class="n">begin</span><span class="p">()</span> </span></span><span class="line"><span class="cl"> <span class="k">await</span> <span class="n">tx</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="s2">&#34;&#34;&#34; </span></span></span><span class="line"><span class="cl"><span class="s2"> MATCH (from:Account {id: $from_id}) </span></span></span><span class="line"><span class="cl"><span class="s2"> SET from.balance = from.balance - $amount </span></span></span><span class="line"><span class="cl"><span class="s2"> &#34;&#34;&#34;</span><span class="p">,</span> <span class="p">{</span><span class="s2">&#34;from_id&#34;</span><span class="p">:</span> <span class="n">from_id</span><span class="p">,</span> <span class="s2">&#34;amount&#34;</span><span class="p">:</span> <span class="n">amount</span><span class="p">})</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="k">await</span> <span class="n">tx</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="s2">&#34;&#34;&#34; </span></span></span><span class="line"><span class="cl"><span class="s2"> MATCH (to:Account {id: $to_id}) </span></span></span><span class="line"><span class="cl"><span class="s2"> SET to.balance = to.balance + $amount </span></span></span><span class="line"><span class="cl"><span class="s2"> &#34;&#34;&#34;</span><span class="p">,</span> <span class="p">{</span><span class="s2">&#34;to_id&#34;</span><span class="p">:</span> <span class="n">to_id</span><span class="p">,</span> <span class="s2">&#34;amount&#34;</span><span class="p">:</span> <span class="n">amount</span><span class="p">})</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="k">await</span> <span class="n">tx</span><span class="o">.</span><span class="n">commit</span><span class="p">()</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="c1"># Execute with retry</span> </span></span><span class="line"><span class="cl"><span class="k">await</span> <span class="n">execute_with_retry</span><span class="p">(</span><span class="k">lambda</span><span class="p">:</span> <span class="n">transfer_money</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mf">100.0</span><span class="p">))</span> </span></span></code></pre></div> <h3 id="performance-monitoring" class="position-relative d-flex align-items-center group"> <span>Performance Monitoring</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="performance-monitoring" aria-haspopup="dialog" aria-label="Share link: Performance Monitoring"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h3> <h4 id="query-performance-tracking" class="position-relative d-flex align-items-center group"> <span>Query Performance Tracking</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="query-performance-tracking" aria-haspopup="dialog" aria-label="Share link: Query Performance Tracking"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h4><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">time</span> </span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">functools</span> <span class="kn">import</span> <span class="n">wraps</span> </span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">prometheus_client</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="c1"># Prometheus metrics</span> </span></span><span class="line"><span class="cl"><span class="n">query_duration</span> <span class="o">=</span> <span class="n">prometheus_client</span><span class="o">.</span><span class="n">Histogram</span><span class="p">(</span> </span></span><span class="line"><span class="cl"> <span class="s1">&#39;geode_query_duration_seconds&#39;</span><span class="p">,</span> </span></span><span class="line"><span class="cl"> <span class="s1">&#39;Query execution time&#39;</span><span class="p">,</span> </span></span><span class="line"><span class="cl"> <span class="p">[</span><span class="s1">&#39;query_type&#39;</span><span class="p">]</span> </span></span><span class="line"><span class="cl"><span class="p">)</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="n">query_counter</span> <span class="o">=</span> <span class="n">prometheus_client</span><span class="o">.</span><span class="n">Counter</span><span class="p">(</span> </span></span><span class="line"><span class="cl"> <span class="s1">&#39;geode_queries_total&#39;</span><span class="p">,</span> </span></span><span class="line"><span class="cl"> <span class="s1">&#39;Total queries executed&#39;</span><span class="p">,</span> </span></span><span class="line"><span class="cl"> <span class="p">[</span><span class="s1">&#39;query_type&#39;</span><span class="p">,</span> <span class="s1">&#39;status&#39;</span><span class="p">]</span> </span></span><span class="line"><span class="cl"><span class="p">)</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">track_query_performance</span><span class="p">(</span><span class="n">query_type</span><span class="p">:</span> <span class="nb">str</span><span class="p">):</span> </span></span><span class="line"><span class="cl"> <span class="s2">&#34;&#34;&#34;Decorator to track query performance.&#34;&#34;&#34;</span> </span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">decorator</span><span class="p">(</span><span class="n">func</span><span class="p">):</span> </span></span><span class="line"><span class="cl"> <span class="nd">@wraps</span><span class="p">(</span><span class="n">func</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="k">async</span> <span class="k">def</span> <span class="nf">wrapper</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span> </span></span><span class="line"><span class="cl"> <span class="n">start_time</span> <span class="o">=</span> <span class="n">time</span><span class="o">.</span><span class="n">perf_counter</span><span class="p">()</span> </span></span><span class="line"><span class="cl"> <span class="n">status</span> <span class="o">=</span> <span class="s1">&#39;success&#39;</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="k">try</span><span class="p">:</span> </span></span><span class="line"><span class="cl"> <span class="n">result</span> <span class="o">=</span> <span class="k">await</span> <span class="n">func</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">result</span> </span></span><span class="line"><span class="cl"> <span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span> </span></span><span class="line"><span class="cl"> <span class="n">status</span> <span class="o">=</span> <span class="s1">&#39;error&#39;</span> </span></span><span class="line"><span class="cl"> <span class="k">raise</span> </span></span><span class="line"><span class="cl"> <span class="k">finally</span><span class="p">:</span> </span></span><span class="line"><span class="cl"> <span class="n">duration</span> <span class="o">=</span> <span class="n">time</span><span class="o">.</span><span class="n">perf_counter</span><span class="p">()</span> <span class="o">-</span> <span class="n">start_time</span> </span></span><span class="line"><span class="cl"> <span class="n">query_duration</span><span class="o">.</span><span class="n">labels</span><span class="p">(</span><span class="n">query_type</span><span class="o">=</span><span class="n">query_type</span><span class="p">)</span><span class="o">.</span><span class="n">observe</span><span class="p">(</span><span class="n">duration</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="n">query_counter</span><span class="o">.</span><span class="n">labels</span><span class="p">(</span><span class="n">query_type</span><span class="o">=</span><span class="n">query_type</span><span class="p">,</span> <span class="n">status</span><span class="o">=</span><span class="n">status</span><span class="p">)</span><span class="o">.</span><span class="n">inc</span><span class="p">()</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">wrapper</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">decorator</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="c1"># Usage</span> </span></span><span class="line"><span class="cl"><span class="nd">@track_query_performance</span><span class="p">(</span><span class="s1">&#39;user_lookup&#39;</span><span class="p">)</span> </span></span><span class="line"><span class="cl"><span class="k">async</span> <span class="k">def</span> <span class="nf">find_user</span><span class="p">(</span><span class="n">email</span><span class="p">:</span> <span class="nb">str</span><span class="p">):</span> </span></span><span class="line"><span class="cl"> <span class="k">async</span> <span class="k">with</span> <span class="n">pool</span><span class="o">.</span><span class="n">acquire</span><span class="p">()</span> <span class="k">as</span> <span class="n">conn</span><span class="p">:</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="k">await</span> <span class="n">conn</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="s2">&#34;&#34;&#34; </span></span></span><span class="line"><span class="cl"><span class="s2"> MATCH (u:User {email: $email}) </span></span></span><span class="line"><span class="cl"><span class="s2"> RETURN u </span></span></span><span class="line"><span class="cl"><span class="s2"> &#34;&#34;&#34;</span><span class="p">,</span> <span class="p">{</span><span class="s2">&#34;email&#34;</span><span class="p">:</span> <span class="n">email</span><span class="p">})</span> </span></span></code></pre></div> <h4 id="slow-query-logging" class="position-relative d-flex align-items-center group"> <span>Slow Query Logging</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="slow-query-logging" aria-haspopup="dialog" aria-label="Share link: Slow Query Logging"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h4><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">SlowQueryLogger</span><span class="p">:</span> </span></span><span class="line"><span class="cl"> <span class="s2">&#34;&#34;&#34;Log queries exceeding threshold.&#34;&#34;&#34;</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">threshold_ms</span><span class="o">=</span><span class="mi">1000</span><span class="p">):</span> </span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">threshold_ms</span> <span class="o">=</span> <span class="n">threshold_ms</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="k">async</span> <span class="k">def</span> <span class="nf">execute</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">conn</span><span class="p">,</span> <span class="n">query</span><span class="p">,</span> <span class="n">params</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span> </span></span><span class="line"><span class="cl"> <span class="s2">&#34;&#34;&#34;Execute query with timing.&#34;&#34;&#34;</span> </span></span><span class="line"><span class="cl"> <span class="n">start</span> <span class="o">=</span> <span class="n">time</span><span class="o">.</span><span class="n">perf_counter</span><span class="p">()</span> </span></span><span class="line"><span class="cl"> <span class="k">try</span><span class="p">:</span> </span></span><span class="line"><span class="cl"> <span class="n">result</span><span class="p">,</span> <span class="n">_</span> <span class="o">=</span> <span class="k">await</span> <span class="n">conn</span><span class="o">.</span><span class="n">query</span><span class="p">(</span><span class="n">query</span><span class="p">,</span> <span class="n">params</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">result</span> </span></span><span class="line"><span class="cl"> <span class="k">finally</span><span class="p">:</span> </span></span><span class="line"><span class="cl"> <span class="n">duration_ms</span> <span class="o">=</span> <span class="p">(</span><span class="n">time</span><span class="o">.</span><span class="n">perf_counter</span><span class="p">()</span> <span class="o">-</span> <span class="n">start</span><span class="p">)</span> <span class="o">*</span> <span class="mi">1000</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">duration_ms</span> <span class="o">&gt;</span> <span class="bp">self</span><span class="o">.</span><span class="n">threshold_ms</span><span class="p">:</span> </span></span><span class="line"><span class="cl"> <span class="n">logging</span><span class="o">.</span><span class="n">warning</span><span class="p">(</span> </span></span><span class="line"><span class="cl"> <span class="sa">f</span><span class="s2">&#34;Slow query (</span><span class="si">{</span><span class="n">duration_ms</span><span class="si">:</span><span class="s2">.2f</span><span class="si">}</span><span class="s2">ms): </span><span class="si">{</span><span class="n">query</span><span class="p">[:</span><span class="mi">100</span><span class="p">]</span><span class="si">}</span><span class="s2">...&#34;</span><span class="p">,</span> </span></span><span class="line"><span class="cl"> <span class="n">extra</span><span class="o">=</span><span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="s1">&#39;duration_ms&#39;</span><span class="p">:</span> <span class="n">duration_ms</span><span class="p">,</span> </span></span><span class="line"><span class="cl"> <span class="s1">&#39;query&#39;</span><span class="p">:</span> <span class="n">query</span><span class="p">,</span> </span></span><span class="line"><span class="cl"> <span class="s1">&#39;params&#39;</span><span class="p">:</span> <span class="n">params</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="p">)</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="c1"># Usage</span> </span></span><span class="line"><span class="cl"><span class="n">logger</span> <span class="o">=</span> <span class="n">SlowQueryLogger</span><span class="p">(</span><span class="n">threshold_ms</span><span class="o">=</span><span class="mi">500</span><span class="p">)</span> </span></span><span class="line"><span class="cl"><span class="k">async</span> <span class="k">with</span> <span class="n">pool</span><span class="o">.</span><span class="n">acquire</span><span class="p">()</span> <span class="k">as</span> <span class="n">conn</span><span class="p">:</span> </span></span><span class="line"><span class="cl"> <span class="n">result</span><span class="p">,</span> <span class="n">_</span> <span class="o">=</span> <span class="k">await</span> <span class="n">logger</span><span class="o">.</span><span class="n">query</span><span class="p">(</span><span class="n">conn</span><span class="p">,</span> <span class="s2">&#34;MATCH (n) RETURN count(n)&#34;</span><span class="p">)</span> </span></span></code></pre></div> <h3 id="code-generation-and-scaffolding" class="position-relative d-flex align-items-center group"> <span>Code Generation and Scaffolding</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="code-generation-and-scaffolding" aria-haspopup="dialog" aria-label="Share link: Code Generation and Scaffolding"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h3> <h4 id="schema-to-code-generator" class="position-relative d-flex align-items-center group"> <span>Schema-to-Code Generator</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="schema-to-code-generator" aria-haspopup="dialog" aria-label="Share link: Schema-to-Code Generator"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h4><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">generate_model_class</span><span class="p">(</span><span class="n">label</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">properties</span><span class="p">:</span> <span class="nb">dict</span><span class="p">):</span> </span></span><span class="line"><span class="cl"> <span class="s2">&#34;&#34;&#34;Generate Python dataclass from graph schema.&#34;&#34;&#34;</span> </span></span><span class="line"><span class="cl"> <span class="n">lines</span> <span class="o">=</span> <span class="p">[</span> </span></span><span class="line"><span class="cl"> <span class="s2">&#34;from dataclasses import dataclass&#34;</span><span class="p">,</span> </span></span><span class="line"><span class="cl"> <span class="s2">&#34;from datetime import datetime&#34;</span><span class="p">,</span> </span></span><span class="line"><span class="cl"> <span class="s2">&#34;from typing import Optional&#34;</span><span class="p">,</span> </span></span><span class="line"><span class="cl"> <span class="s2">&#34;&#34;</span><span class="p">,</span> </span></span><span class="line"><span class="cl"> <span class="s2">&#34;@dataclass&#34;</span><span class="p">,</span> </span></span><span class="line"><span class="cl"> <span class="sa">f</span><span class="s2">&#34;class </span><span class="si">{</span><span class="n">label</span><span class="si">}</span><span class="s2">:&#34;</span> </span></span><span class="line"><span class="cl"> <span class="p">]</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">prop_name</span><span class="p">,</span> <span class="n">prop_type</span> <span class="ow">in</span> <span class="n">properties</span><span class="o">.</span><span class="n">items</span><span class="p">():</span> </span></span><span class="line"><span class="cl"> <span class="n">python_type</span> <span class="o">=</span> <span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="s1">&#39;string&#39;</span><span class="p">:</span> <span class="s1">&#39;str&#39;</span><span class="p">,</span> </span></span><span class="line"><span class="cl"> <span class="s1">&#39;integer&#39;</span><span class="p">:</span> <span class="s1">&#39;int&#39;</span><span class="p">,</span> </span></span><span class="line"><span class="cl"> <span class="s1">&#39;float&#39;</span><span class="p">:</span> <span class="s1">&#39;float&#39;</span><span class="p">,</span> </span></span><span class="line"><span class="cl"> <span class="s1">&#39;boolean&#39;</span><span class="p">:</span> <span class="s1">&#39;bool&#39;</span><span class="p">,</span> </span></span><span class="line"><span class="cl"> <span class="s1">&#39;datetime&#39;</span><span class="p">:</span> <span class="s1">&#39;datetime&#39;</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">prop_type</span><span class="p">,</span> <span class="s1">&#39;str&#39;</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="n">lines</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34; </span><span class="si">{</span><span class="n">prop_name</span><span class="si">}</span><span class="s2">: Optional[</span><span class="si">{</span><span class="n">python_type</span><span class="si">}</span><span class="s2">] = None&#34;</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="s2">&#34;</span><span class="se">\n</span><span class="s2">&#34;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">lines</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="c1"># Generate from schema</span> </span></span><span class="line"><span class="cl"><span class="n">schema</span> <span class="o">=</span> <span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="s1">&#39;User&#39;</span><span class="p">:</span> <span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="s1">&#39;id&#39;</span><span class="p">:</span> <span class="s1">&#39;integer&#39;</span><span class="p">,</span> </span></span><span class="line"><span class="cl"> <span class="s1">&#39;name&#39;</span><span class="p">:</span> <span class="s1">&#39;string&#39;</span><span class="p">,</span> </span></span><span class="line"><span class="cl"> <span class="s1">&#39;email&#39;</span><span class="p">:</span> <span class="s1">&#39;string&#39;</span><span class="p">,</span> </span></span><span class="line"><span class="cl"> <span class="s1">&#39;created&#39;</span><span class="p">:</span> <span class="s1">&#39;datetime&#39;</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"><span class="p">}</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="k">for</span> <span class="n">label</span><span class="p">,</span> <span class="n">properties</span> <span class="ow">in</span> <span class="n">schema</span><span class="o">.</span><span class="n">items</span><span class="p">():</span> </span></span><span class="line"><span class="cl"> <span class="n">code</span> <span class="o">=</span> <span class="n">generate_model_class</span><span class="p">(</span><span class="n">label</span><span class="p">,</span> <span class="n">properties</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="nb">print</span><span class="p">(</span><span class="n">code</span><span class="p">)</span> </span></span></code></pre></div> <h3 id="continuous-integration-examples" class="position-relative d-flex align-items-center group"> <span>Continuous Integration Examples</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="continuous-integration-examples" aria-haspopup="dialog" aria-label="Share link: Continuous Integration Examples"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h3> <h4 id="github-actions-workflow" class="position-relative d-flex align-items-center group"> <span>GitHub Actions Workflow</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="github-actions-workflow" aria-haspopup="dialog" aria-label="Share link: GitHub Actions Workflow"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h4><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Geode Integration Tests</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">on</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="l">push, pull_request]</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">jobs</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">test</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">runs-on</span><span class="p">:</span><span class="w"> </span><span class="l">ubuntu-latest</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">services</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">geode</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">codepros/geode:latest</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">ports</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="m">3141</span><span class="p">:</span><span class="m">3141</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">options</span><span class="p">:</span><span class="w"> </span><span class="p">&gt;-</span><span class="sd"> </span></span></span><span class="line"><span class="cl"><span class="sd"> --health-cmd &#34;geode ping&#34; </span></span></span><span class="line"><span class="cl"><span class="sd"> --health-interval 10s </span></span></span><span class="line"><span class="cl"><span class="sd"> --health-timeout 5s </span></span></span><span class="line"><span class="cl"><span class="sd"> --health-retries 5</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">steps</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">uses</span><span class="p">:</span><span class="w"> </span><span class="l">actions/checkout@v3</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Set up Python</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">uses</span><span class="p">:</span><span class="w"> </span><span class="l">actions/setup-python@v4</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">with</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">python-version</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;3.11&#39;</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Install dependencies</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">run</span><span class="p">:</span><span class="w"> </span><span class="p">|</span><span class="sd"> </span></span></span><span class="line"><span class="cl"><span class="sd"> pip install -r requirements.txt </span></span></span><span class="line"><span class="cl"><span class="sd"> pip install pytest pytest-asyncio</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Wait for Geode</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">run</span><span class="p">:</span><span class="w"> </span><span class="p">|</span><span class="sd"> </span></span></span><span class="line"><span class="cl"><span class="sd"> timeout 30 sh -c &#39;until geode ping; do sleep 1; done&#39;</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Run tests</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">env</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">GEODE_URL</span><span class="p">:</span><span class="w"> </span><span class="l">quic://localhost:3141</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">run</span><span class="p">:</span><span class="w"> </span><span class="l">pytest tests/</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Upload coverage</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">uses</span><span class="p">:</span><span class="w"> </span><span class="l">codecov/codecov-action@v3</span><span class="w"> </span></span></span></code></pre></div> <h4 id="docker-compose-for-development" class="position-relative d-flex align-items-center group"> <span>Docker Compose for Development</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="docker-compose-for-development" aria-haspopup="dialog" aria-label="Share link: Docker Compose for Development"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h4><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">version</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;3.8&#39;</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">services</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">geode</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">codepros/geode:v0.2.18</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">ports</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="s2">&#34;3141:3141&#34;</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">volumes</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">geode-data:/var/lib/geode</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">environment</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">GEODE_LOG_LEVEL=debug</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">healthcheck</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">test</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">&#34;CMD&#34;</span><span class="p">,</span><span class="w"> </span><span class="s2">&#34;geode&#34;</span><span class="p">,</span><span class="w"> </span><span class="s2">&#34;ping&#34;</span><span class="p">]</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">interval</span><span class="p">:</span><span class="w"> </span><span class="l">10s</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">timeout</span><span class="p">:</span><span class="w"> </span><span class="l">5s</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">retries</span><span class="p">:</span><span class="w"> </span><span class="m">3</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">prometheus</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">prom/prometheus:latest</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">ports</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="s2">&#34;9090:9090&#34;</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">volumes</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">./prometheus.yml:/etc/prometheus/prometheus.yml</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">grafana</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">grafana/grafana:latest</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">ports</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="s2">&#34;3000:3000&#34;</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">environment</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">GF_SECURITY_ADMIN_PASSWORD=admin</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">depends_on</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">prometheus</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">volumes</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">geode-data</span><span class="p">:</span><span class="w"> </span></span></span></code></pre></div> <h3 id="further-reading" class="position-relative d-flex align-items-center group"> <span>Further Reading</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="further-reading" aria-haspopup="dialog" aria-label="Share link: Further Reading"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h3><ul> <li><a href="/docs/getting-started/" >Getting Started Guide</a> - Initial setup and first queries</li> <li><a href="/docs/client-libraries/" >Client Library Documentation</a> - SDK references</li> <li><a href="/docs/tutorials/repl-basics/" >REPL Basics Tutorial</a> - Interactive shell documentation</li> <li><a href="/docs/development/lsp-guide/" >LSP Guide</a> - IDE integration</li> <li><a href="/docs/api-reference/" >API Reference</a> - Complete API documentation</li> <li><a href="/docs/development/testing-guide/" >Testing Guide</a> - Coding and testing guidelines</li> <li><a href="/docs/ops/observability/" >Observability</a> - Monitoring and observability setup</li> </ul>

Related Articles