<!-- CANARY: REQ=REQ-DOCS-001; FEATURE="Docs"; ASPECT=Documentation; STATUS=TESTED; OWNER=docs; UPDATED=2026-01-28 --> <h2 id="backup-and-restore-guide" class="position-relative d-flex align-items-center group"> <span>Backup and Restore Guide</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="backup-and-restore-guide" aria-haspopup="dialog" aria-label="Share link: Backup and Restore Guide"> <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> </h2><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>This guide covers comprehensive backup and restore strategies for Geode databases. Learn how to implement online and offline backups, full and incremental backups, point-in-time recovery, and disaster recovery planning.</p> <h3 id="overview" class="position-relative d-flex align-items-center group"> <span>Overview</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="overview" aria-haspopup="dialog" aria-label="Share link: Overview"> <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><p>Geode provides multiple backup strategies to protect your data:</p> <table> <thead> <tr> <th>Backup Type</th> <th>Description</th> <th>Use Case</th> </tr> </thead> <tbody> <tr> <td>Online Backup</td> <td>No downtime required</td> <td>Production systems</td> </tr> <tr> <td>Offline Backup</td> <td>Database stopped</td> <td>Maintenance windows</td> </tr> <tr> <td>Full Backup</td> <td>Complete database copy</td> <td>Weekly/monthly backups</td> </tr> <tr> <td>Incremental Backup</td> <td>Changes since last backup</td> <td>Daily backups</td> </tr> <tr> <td>Point-in-Time</td> <td>Restore to specific moment</td> <td>Data recovery</td> </tr> <tr> <td>Snapshot</td> <td>Instant copy</td> <td>Testing, development</td> </tr> </tbody> </table> <h3 id="backup-architecture" class="position-relative d-flex align-items-center group"> <span>Backup Architecture</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="backup-architecture" aria-haspopup="dialog" aria-label="Share link: Backup Architecture"> <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 class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">Geode Database </span></span><span class="line"><span class="cl"> | </span></span><span class="line"><span class="cl"> +-- Data Files (*.gdb) </span></span><span class="line"><span class="cl"> | </span></span><span class="line"><span class="cl"> +-- Transaction Logs (*.wal) </span></span><span class="line"><span class="cl"> | </span></span><span class="line"><span class="cl"> +-- Configuration (geode.conf) </span></span><span class="line"><span class="cl"> | </span></span><span class="line"><span class="cl"> +-- Metadata (schemas, indexes) </span></span></code></pre></div> <h3 id="online-vs-offline-backups" class="position-relative d-flex align-items-center group"> <span>Online vs Offline Backups</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="online-vs-offline-backups" aria-haspopup="dialog" aria-label="Share link: Online vs Offline Backups"> <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="online-backups-hot-backup" class="position-relative d-flex align-items-center group"> <span>Online Backups (Hot Backup)</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="online-backups-hot-backup" aria-haspopup="dialog" aria-label="Share link: Online Backups (Hot Backup)"> <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>Online backups allow you to back up the database while it&rsquo;s running and serving traffic.</p> <p><strong>Advantages</strong>:</p> <ul> <li>No downtime</li> <li>Consistent snapshot</li> <li>Suitable for 24/7 operations</li> </ul> <p><strong>CLI Command</strong>:</p> <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># Create online backup</span> </span></span><span class="line"><span class="cl">geode backup create <span class="se">\ </span></span></span><span class="line"><span class="cl"><span class="se"></span> --output /backups/geode-<span class="k">$(</span>date +%Y%m%d-%H%M%S<span class="k">)</span>.backup <span class="se">\ </span></span></span><span class="line"><span class="cl"><span class="se"></span> --compress <span class="se">\ </span></span></span><span class="line"><span class="cl"><span class="se"></span> --verify </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="c1"># With specific connection</span> </span></span><span class="line"><span class="cl">geode backup create <span class="se">\ </span></span></span><span class="line"><span class="cl"><span class="se"></span> --host localhost:3141 <span class="se">\ </span></span></span><span class="line"><span class="cl"><span class="se"></span> --output /backups/full-backup.backup </span></span></code></pre></div><p><strong>Multi-Language Online Backup Examples</strong>:</p> <div class="docs-tabs mb-4"> <ul class="nav nav-tabs" id="tabs-1774880883800779365" role="tablist"><li class="nav-item" role="presentation"> <button class="nav-link active" id="tabs-1774880883800779365-tab-0-tab" data-bs-toggle="tab" data-bs-target="#tabs-1774880883800779365-tab-0" type="button" role="tab" aria-controls="tabs-1774880883800779365-tab-0" aria-selected="true" > Go </button> </li><li class="nav-item" role="presentation"> <button class="nav-link" id="tabs-1774880883800779365-tab-1-tab" data-bs-toggle="tab" data-bs-target="#tabs-1774880883800779365-tab-1" type="button" role="tab" aria-controls="tabs-1774880883800779365-tab-1" aria-selected="false" > Python </button> </li><li class="nav-item" role="presentation"> <button class="nav-link" id="tabs-1774880883800779365-tab-2-tab" data-bs-toggle="tab" data-bs-target="#tabs-1774880883800779365-tab-2" type="button" role="tab" aria-controls="tabs-1774880883800779365-tab-2" aria-selected="false" > Rust </button> </li><li class="nav-item" role="presentation"> <button class="nav-link" id="tabs-1774880883800779365-tab-3-tab" data-bs-toggle="tab" data-bs-target="#tabs-1774880883800779365-tab-3" type="button" role="tab" aria-controls="tabs-1774880883800779365-tab-3" aria-selected="false" > Bash </button> </li></ul> <div class="tab-content border border-top-0 rounded-bottom p-3" id="tabs-1774880883800779365-content"><div class="tab-pane fade show active" id="tabs-1774880883800779365-tab-0" role="tabpanel" aria-labelledby="tabs-1774880883800779365-tab-0-tab" > <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;fmt&#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 class="s">&#34;time&#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">func</span> <span class="nf">createOnlineBackup</span><span class="p">(</span><span class="nx">db</span> <span class="o">*</span><span class="nx">sql</span><span class="p">.</span><span class="nx">DB</span><span class="p">,</span> <span class="nx">backupPath</span> <span class="kt">string</span><span class="p">)</span> <span class="kt">error</span> <span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">ctx</span> <span class="o">:=</span> <span class="nx">context</span><span class="p">.</span><span class="nf">Background</span><span class="p">()</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="c1">// Start backup </span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">_</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">ExecContext</span><span class="p">(</span><span class="nx">ctx</span><span class="p">,</span> </span></span><span class="line"><span class="cl"> <span class="s">&#34;CALL geode.backup.create($path, $compress)&#34;</span><span class="p">,</span> </span></span><span class="line"><span class="cl"> <span class="nx">backupPath</span><span class="p">,</span> <span class="kc">true</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="nx">fmt</span><span class="p">.</span><span class="nf">Errorf</span><span class="p">(</span><span class="s">&#34;backup failed: %w&#34;</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="c1">// Verify backup </span></span></span><span class="line"><span class="cl"><span class="c1"></span> <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">ctx</span><span class="p">,</span> </span></span><span class="line"><span class="cl"> <span class="s">&#34;CALL geode.backup.verify($path)&#34;</span><span class="p">,</span> </span></span><span class="line"><span class="cl"> <span class="nx">backupPath</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="nx">fmt</span><span class="p">.</span><span class="nf">Errorf</span><span class="p">(</span><span class="s">&#34;verification failed: %w&#34;</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 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">valid</span> <span class="kt">bool</span> </span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">checksum</span> <span class="kt">string</span> </span></span><span class="line"><span class="cl"> <span class="k">if</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="nx">rows</span><span class="p">.</span><span class="nf">Scan</span><span class="p">(</span><span class="o">&amp;</span><span class="nx">valid</span><span class="p">,</span> <span class="o">&amp;</span><span class="nx">checksum</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">!</span><span class="nx">valid</span> <span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Errorf</span><span class="p">(</span><span class="s">&#34;backup verification failed&#34;</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="nx">log</span><span class="p">.</span><span class="nf">Printf</span><span class="p">(</span><span class="s">&#34;Backup verified: checksum=%s&#34;</span><span class="p">,</span> <span class="nx">checksum</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="kc">nil</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">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;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="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 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">backupPath</span> <span class="o">:=</span> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Sprintf</span><span class="p">(</span><span class="s">&#34;/backups/geode-%s.backup&#34;</span><span class="p">,</span> </span></span><span class="line"><span class="cl"> <span class="nx">time</span><span class="p">.</span><span class="nf">Now</span><span class="p">().</span><span class="nf">Format</span><span class="p">(</span><span class="s">&#34;20060102-150405&#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">if</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nf">createOnlineBackup</span><span class="p">(</span><span class="nx">db</span><span class="p">,</span> <span class="nx">backupPath</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="nx">log</span><span class="p">.</span><span class="nf">Fatalf</span><span class="p">(</span><span class="s">&#34;Backup failed: %v&#34;</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="nx">log</span><span class="p">.</span><span class="nf">Printf</span><span class="p">(</span><span class="s">&#34;Backup created successfully: %s&#34;</span><span class="p">,</span> <span class="nx">backupPath</span><span class="p">)</span> </span></span><span class="line"><span class="cl"><span class="p">}</span> </span></span></code></pre></div> </div><div class="tab-pane fade" id="tabs-1774880883800779365-tab-1" role="tabpanel" aria-labelledby="tabs-1774880883800779365-tab-1-tab" > <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">asyncio</span> </span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">datetime</span> <span class="kn">import</span> <span class="n">datetime</span> </span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">geode_client</span> <span class="kn">import</span> <span class="n">Client</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">create_online_backup</span><span class="p">(</span><span class="n">backup_path</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;Create an online backup without stopping the database.&#34;&#34;&#34;</span> </span></span><span class="line"><span class="cl"> <span class="n">client</span> <span class="o">=</span> <span class="n">Client</span><span class="p">(</span><span class="n">host</span><span class="o">=</span><span class="s2">&#34;localhost&#34;</span><span class="p">,</span> <span class="n">port</span><span class="o">=</span><span class="mi">3141</span><span class="p">,</span> <span class="n">skip_verify</span><span class="o">=</span><span class="kc">True</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">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"># Start backup</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;Starting online backup to </span><span class="si">{</span><span class="n">backup_path</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">await</span> <span class="n">conn</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span> </span></span><span class="line"><span class="cl"> <span class="s2">&#34;CALL geode.backup.create($path, $compress)&#34;</span><span class="p">,</span> </span></span><span class="line"><span class="cl"> <span class="p">{</span><span class="s2">&#34;path&#34;</span><span class="p">:</span> <span class="n">backup_path</span><span class="p">,</span> <span class="s2">&#34;compress&#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="p">)</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="c1"># Verify backup integrity</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></span><span class="line"><span class="cl"> <span class="s2">&#34;CALL geode.backup.verify($path)&#34;</span><span class="p">,</span> </span></span><span class="line"><span class="cl"> <span class="p">{</span><span class="s2">&#34;path&#34;</span><span class="p">:</span> <span class="n">backup_path</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">if</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">row</span> <span class="o">=</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></span><span class="line"><span class="cl"> <span class="n">valid</span> <span class="o">=</span> <span class="n">row</span><span class="p">[</span><span class="s1">&#39;valid&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">as_bool</span> </span></span><span class="line"><span class="cl"> <span class="n">checksum</span> <span class="o">=</span> <span class="n">row</span><span class="p">[</span><span class="s1">&#39;checksum&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">as_string</span> </span></span><span class="line"><span class="cl"> <span class="n">size_mb</span> <span class="o">=</span> <span class="n">row</span><span class="p">[</span><span class="s1">&#39;size_bytes&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">as_int</span> <span class="o">/</span> <span class="p">(</span><span class="mi">1024</span> <span class="o">*</span> <span class="mi">1024</span><span class="p">)</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">valid</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;Backup verified successfully&#34;</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; Checksum: </span><span class="si">{</span><span class="n">checksum</span><span class="si">}</span><span class="s2">&#34;</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; Size: </span><span class="si">{</span><span class="n">size_mb</span><span class="si">:</span><span class="s2">.2f</span><span class="si">}</span><span class="s2"> MB&#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="k">raise</span> <span class="ne">Exception</span><span class="p">(</span><span class="s2">&#34;Backup verification failed&#34;</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="sa">f</span><span class="s2">&#34;Online backup complete: </span><span class="si">{</span><span class="n">backup_path</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">async</span> <span class="k">def</span> <span class="nf">main</span><span class="p">():</span> </span></span><span class="line"><span class="cl"> <span class="n">timestamp</span> <span class="o">=</span> <span class="n">datetime</span><span class="o">.</span><span class="n">now</span><span class="p">()</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="s2">&#34;%Y%m</span><span class="si">%d</span><span class="s2">-%H%M%S&#34;</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="n">backup_path</span> <span class="o">=</span> <span class="sa">f</span><span class="s2">&#34;/backups/geode-</span><span class="si">{</span><span class="n">timestamp</span><span class="si">}</span><span class="s2">.backup&#34;</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">create_online_backup</span><span class="p">(</span><span class="n">backup_path</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="n">asyncio</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="n">main</span><span class="p">())</span> </span></span></code></pre></div> </div><div class="tab-pane fade" id="tabs-1774880883800779365-tab-2" role="tabpanel" aria-labelledby="tabs-1774880883800779365-tab-2-tab" > <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="cl"><span class="k">use</span><span class="w"> </span><span class="n">geode_client</span>::<span class="p">{</span><span class="n">Client</span><span class="p">,</span><span class="w"> </span><span class="n">Value</span><span class="p">};</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="k">use</span><span class="w"> </span><span class="n">std</span>::<span class="n">collections</span>::<span class="n">HashMap</span><span class="p">;</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="k">use</span><span class="w"> </span><span class="n">chrono</span>::<span class="n">Local</span><span class="p">;</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="cp">#[tokio::main]</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="k">async</span><span class="w"> </span><span class="k">fn</span> <span class="nf">main</span><span class="p">()</span><span class="w"> </span>-&gt; <span class="nb">Result</span><span class="o">&lt;</span><span class="p">(),</span><span class="w"> </span><span class="nb">Box</span><span class="o">&lt;</span><span class="k">dyn</span><span class="w"> </span><span class="n">std</span>::<span class="n">error</span>::<span class="n">Error</span><span class="o">&gt;&gt;</span><span class="w"> </span><span class="p">{</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">client</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Client</span>::<span class="n">new</span><span class="p">(</span><span class="s">&#34;127.0.0.1&#34;</span><span class="p">,</span><span class="w"> </span><span class="mi">3141</span><span class="p">).</span><span class="n">skip_verify</span><span class="p">(</span><span class="kc">true</span><span class="p">);</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">conn</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">client</span><span class="p">.</span><span class="n">connect</span><span class="p">().</span><span class="k">await</span><span class="o">?</span><span class="p">;</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="kd">let</span><span class="w"> </span><span class="n">timestamp</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Local</span>::<span class="n">now</span><span class="p">().</span><span class="n">format</span><span class="p">(</span><span class="s">&#34;%Y%m%d-%H%M%S&#34;</span><span class="p">);</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">backup_path</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="fm">format!</span><span class="p">(</span><span class="s">&#34;/backups/geode-</span><span class="si">{}</span><span class="s">.backup&#34;</span><span class="p">,</span><span class="w"> </span><span class="n">timestamp</span><span class="p">);</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="fm">println!</span><span class="p">(</span><span class="s">&#34;Starting online backup to </span><span class="si">{}</span><span class="s">...&#34;</span><span class="p">,</span><span class="w"> </span><span class="n">backup_path</span><span class="p">);</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="c1">// Create backup </span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">params</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">HashMap</span>::<span class="n">new</span><span class="p">();</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">params</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="s">&#34;path&#34;</span><span class="p">.</span><span class="n">to_string</span><span class="p">(),</span><span class="w"> </span><span class="n">Value</span>::<span class="n">string</span><span class="p">(</span><span class="o">&amp;</span><span class="n">backup_path</span><span class="p">));</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">params</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="s">&#34;compress&#34;</span><span class="p">.</span><span class="n">to_string</span><span class="p">(),</span><span class="w"> </span><span class="n">Value</span>::<span class="kt">bool</span><span class="p">(</span><span class="kc">true</span><span class="p">));</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="n">conn</span><span class="p">.</span><span class="n">query_with_params</span><span class="p">(</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="s">&#34;CALL geode.backup.create($path, $compress)&#34;</span><span class="p">,</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="o">&amp;</span><span class="n">params</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="p">).</span><span class="k">await</span><span class="o">?</span><span class="p">;</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="c1">// Verify backup </span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">verify_params</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">HashMap</span>::<span class="n">new</span><span class="p">();</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">verify_params</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="s">&#34;path&#34;</span><span class="p">.</span><span class="n">to_string</span><span class="p">(),</span><span class="w"> </span><span class="n">Value</span>::<span class="n">string</span><span class="p">(</span><span class="o">&amp;</span><span class="n">backup_path</span><span class="p">));</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="kd">let</span><span class="w"> </span><span class="p">(</span><span class="n">result</span><span class="p">,</span><span class="w"> </span><span class="n">_</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">conn</span><span class="p">.</span><span class="n">query_with_params</span><span class="p">(</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="s">&#34;CALL geode.backup.verify($path)&#34;</span><span class="p">,</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="o">&amp;</span><span class="n">verify_params</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="p">).</span><span class="k">await</span><span class="o">?</span><span class="p">;</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="k">if</span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nb">Some</span><span class="p">(</span><span class="n">row</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">result</span><span class="p">.</span><span class="n">rows</span><span class="p">.</span><span class="n">first</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">valid</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">row</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#34;valid&#34;</span><span class="p">).</span><span class="n">unwrap</span><span class="p">().</span><span class="n">as_bool</span><span class="p">()</span><span class="o">?</span><span class="p">;</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">checksum</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">row</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#34;checksum&#34;</span><span class="p">).</span><span class="n">unwrap</span><span class="p">().</span><span class="n">as_string</span><span class="p">()</span><span class="o">?</span><span class="p">;</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="k">if</span><span class="w"> </span><span class="n">valid</span><span class="w"> </span><span class="p">{</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="fm">println!</span><span class="p">(</span><span class="s">&#34;Backup verified: checksum=</span><span class="si">{}</span><span class="s">&#34;</span><span class="p">,</span><span class="w"> </span><span class="n">checksum</span><span class="p">);</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nb">Err</span><span class="p">(</span><span class="s">&#34;Backup verification failed&#34;</span><span class="p">.</span><span class="n">into</span><span class="p">());</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="p">}</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="p">}</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="fm">println!</span><span class="p">(</span><span class="s">&#34;Online backup complete: </span><span class="si">{}</span><span class="s">&#34;</span><span class="p">,</span><span class="w"> </span><span class="n">backup_path</span><span class="p">);</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nb">Ok</span><span class="p">(())</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">}</span><span class="w"> </span></span></span></code></pre></div> </div><div class="tab-pane fade" id="tabs-1774880883800779365-tab-3" role="tabpanel" aria-labelledby="tabs-1774880883800779365-tab-3-tab" > <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="cp">#!/bin/bash </span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="c1"># Online backup script</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="nb">set</span> -euo pipefail </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="nv">BACKUP_DIR</span><span class="o">=</span><span class="s2">&#34;/backups&#34;</span> </span></span><span class="line"><span class="cl"><span class="nv">TIMESTAMP</span><span class="o">=</span><span class="k">$(</span>date +%Y%m%d-%H%M%S<span class="k">)</span> </span></span><span class="line"><span class="cl"><span class="nv">BACKUP_FILE</span><span class="o">=</span><span class="s2">&#34;</span><span class="si">${</span><span class="nv">BACKUP_DIR</span><span class="si">}</span><span class="s2">/geode-</span><span class="si">${</span><span class="nv">TIMESTAMP</span><span class="si">}</span><span class="s2">.backup&#34;</span> </span></span><span class="line"><span class="cl"><span class="nv">GEODE_HOST</span><span class="o">=</span><span class="s2">&#34;localhost:3141&#34;</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;Starting online backup...&#34;</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="c1"># Create backup</span> </span></span><span class="line"><span class="cl">geode backup create <span class="se">\ </span></span></span><span class="line"><span class="cl"><span class="se"></span> --host <span class="s2">&#34;</span><span class="si">${</span><span class="nv">GEODE_HOST</span><span class="si">}</span><span class="s2">&#34;</span> <span class="se">\ </span></span></span><span class="line"><span class="cl"><span class="se"></span> --output <span class="s2">&#34;</span><span class="si">${</span><span class="nv">BACKUP_FILE</span><span class="si">}</span><span class="s2">&#34;</span> <span class="se">\ </span></span></span><span class="line"><span class="cl"><span class="se"></span> --compress <span class="se">\ </span></span></span><span class="line"><span class="cl"><span class="se"></span> --verify </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="c1"># Check result</span> </span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="o">[</span> <span class="nv">$?</span> -eq <span class="m">0</span> <span class="o">]</span><span class="p">;</span> <span class="k">then</span> </span></span><span class="line"><span class="cl"> <span class="nv">SIZE</span><span class="o">=</span><span class="k">$(</span>du -h <span class="s2">&#34;</span><span class="si">${</span><span class="nv">BACKUP_FILE</span><span class="si">}</span><span class="s2">&#34;</span> <span class="p">|</span> cut -f1<span class="k">)</span> </span></span><span class="line"><span class="cl"> <span class="nb">echo</span> <span class="s2">&#34;Backup complete: </span><span class="si">${</span><span class="nv">BACKUP_FILE</span><span class="si">}</span><span class="s2"> (</span><span class="si">${</span><span class="nv">SIZE</span><span class="si">}</span><span class="s2">)&#34;</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="c1"># Keep only last 7 daily backups</span> </span></span><span class="line"><span class="cl"> find <span class="s2">&#34;</span><span class="si">${</span><span class="nv">BACKUP_DIR</span><span class="si">}</span><span class="s2">&#34;</span> -name <span class="s2">&#34;geode-*.backup&#34;</span> -mtime +7 -delete </span></span><span class="line"><span class="cl"> <span class="nb">echo</span> <span class="s2">&#34;Cleaned up old backups&#34;</span> </span></span><span class="line"><span class="cl"><span class="k">else</span> </span></span><span class="line"><span class="cl"> <span class="nb">echo</span> <span class="s2">&#34;Backup failed!&#34;</span> </span></span><span class="line"><span class="cl"> <span class="nb">exit</span> <span class="m">1</span> </span></span><span class="line"><span class="cl"><span class="k">fi</span> </span></span></code></pre></div> </div></div> </div> <h4 id="offline-backups-cold-backup" class="position-relative d-flex align-items-center group"> <span>Offline Backups (Cold Backup)</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="offline-backups-cold-backup" aria-haspopup="dialog" aria-label="Share link: Offline Backups (Cold Backup)"> <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>Offline backups require stopping the database but guarantee complete consistency.</p> <p><strong>CLI Commands</strong>:</p> <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># Stop Geode</span> </span></span><span class="line"><span class="cl">systemctl stop geode </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="c1"># Create backup (filesystem copy)</span> </span></span><span class="line"><span class="cl">tar -czvf /backups/geode-offline-<span class="k">$(</span>date +%Y%m%d<span class="k">)</span>.tar.gz /var/lib/geode/data </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="c1"># Restart Geode</span> </span></span><span class="line"><span class="cl">systemctl start geode </span></span></code></pre></div><p><strong>When to Use Offline Backups</strong>:</p> <ul> <li>Major version upgrades</li> <li>Schema migrations</li> <li>Hardware maintenance</li> <li>Compliance requirements</li> </ul> <h3 id="full-backups" class="position-relative d-flex align-items-center group"> <span>Full Backups</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="full-backups" aria-haspopup="dialog" aria-label="Share link: Full Backups"> <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="creating-full-backups" class="position-relative d-flex align-items-center group"> <span>Creating Full Backups</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="creating-full-backups" aria-haspopup="dialog" aria-label="Share link: Creating Full Backups"> <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>A full backup contains the complete database state.</p> <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># Full backup with metadata</span> </span></span><span class="line"><span class="cl">geode backup full <span class="se">\ </span></span></span><span class="line"><span class="cl"><span class="se"></span> --output /backups/full-<span class="k">$(</span>date +%Y%m%d<span class="k">)</span>.backup <span class="se">\ </span></span></span><span class="line"><span class="cl"><span class="se"></span> --include-metadata <span class="se">\ </span></span></span><span class="line"><span class="cl"><span class="se"></span> --include-indexes <span class="se">\ </span></span></span><span class="line"><span class="cl"><span class="se"></span> --compress gzip <span class="se">\ </span></span></span><span class="line"><span class="cl"><span class="se"></span> --compression-level <span class="m">6</span> </span></span></code></pre></div> <h4 id="full-backup-schedule" class="position-relative d-flex align-items-center group"> <span>Full Backup Schedule</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="full-backup-schedule" aria-haspopup="dialog" aria-label="Share link: Full Backup Schedule"> <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">asyncio</span> </span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">os</span> </span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">datetime</span> <span class="kn">import</span> <span class="n">datetime</span> </span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">geode_client</span> <span class="kn">import</span> <span class="n">Client</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">create_full_backup</span><span class="p">():</span> </span></span><span class="line"><span class="cl"> <span class="s2">&#34;&#34;&#34;Create a full backup with all data and metadata.&#34;&#34;&#34;</span> </span></span><span class="line"><span class="cl"> <span class="n">client</span> <span class="o">=</span> <span class="n">Client</span><span class="p">(</span><span class="n">host</span><span class="o">=</span><span class="s2">&#34;localhost&#34;</span><span class="p">,</span> <span class="n">port</span><span class="o">=</span><span class="mi">3141</span><span class="p">,</span> <span class="n">skip_verify</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="n">backup_dir</span> <span class="o">=</span> <span class="s2">&#34;/backups/full&#34;</span> </span></span><span class="line"><span class="cl"> <span class="n">os</span><span class="o">.</span><span class="n">makedirs</span><span class="p">(</span><span class="n">backup_dir</span><span class="p">,</span> <span class="n">exist_ok</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="n">timestamp</span> <span class="o">=</span> <span class="n">datetime</span><span class="o">.</span><span class="n">now</span><span class="p">()</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="s2">&#34;%Y%m</span><span class="si">%d</span><span class="s2">&#34;</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="n">backup_path</span> <span class="o">=</span> <span class="sa">f</span><span class="s2">&#34;</span><span class="si">{</span><span class="n">backup_dir</span><span class="si">}</span><span class="s2">/geode-full-</span><span class="si">{</span><span class="n">timestamp</span><span class="si">}</span><span class="s2">.backup&#34;</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">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"># Create full backup with all options</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></span><span class="line"><span class="cl"> <span class="s2">&#34;&#34;&#34;CALL geode.backup.full($path, { </span></span></span><span class="line"><span class="cl"><span class="s2"> include_metadata: true, </span></span></span><span class="line"><span class="cl"><span class="s2"> include_indexes: true, </span></span></span><span class="line"><span class="cl"><span class="s2"> compression: &#39;gzip&#39;, </span></span></span><span class="line"><span class="cl"><span class="s2"> compression_level: 6 </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 class="p">{</span><span class="s2">&#34;path&#34;</span><span class="p">:</span> <span class="n">backup_path</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="c1"># Get backup info</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></span><span class="line"><span class="cl"> <span class="s2">&#34;CALL geode.backup.info($path)&#34;</span><span class="p">,</span> </span></span><span class="line"><span class="cl"> <span class="p">{</span><span class="s2">&#34;path&#34;</span><span class="p">:</span> <span class="n">backup_path</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">if</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">info</span> <span class="o">=</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></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;Full backup created: </span><span class="si">{</span><span class="n">backup_path</span><span class="si">}</span><span class="s2">&#34;</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; Nodes: </span><span class="si">{</span><span class="n">info</span><span class="p">[</span><span class="s1">&#39;node_count&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">as_int</span><span class="si">:</span><span class="s2">,</span><span class="si">}</span><span class="s2">&#34;</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; Relationships: </span><span class="si">{</span><span class="n">info</span><span class="p">[</span><span class="s1">&#39;relationship_count&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">as_int</span><span class="si">:</span><span class="s2">,</span><span class="si">}</span><span class="s2">&#34;</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; Size: </span><span class="si">{</span><span class="n">info</span><span class="p">[</span><span class="s1">&#39;size_bytes&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">as_int</span> <span class="o">/</span> <span class="p">(</span><span class="mi">1024</span><span class="o">*</span><span class="mi">1024</span><span class="p">)</span><span class="si">:</span><span class="s2">.2f</span><span class="si">}</span><span class="s2"> MB&#34;</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; Duration: </span><span class="si">{</span><span class="n">info</span><span class="p">[</span><span class="s1">&#39;duration_ms&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">as_int</span><span class="si">}</span><span class="s2"> ms&#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">asyncio</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="n">create_full_backup</span><span class="p">())</span> </span></span></code></pre></div> <h3 id="incremental-backups" class="position-relative d-flex align-items-center group"> <span>Incremental Backups</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="incremental-backups" aria-haspopup="dialog" aria-label="Share link: Incremental Backups"> <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="understanding-incremental-backups" class="position-relative d-flex align-items-center group"> <span>Understanding Incremental Backups</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="understanding-incremental-backups" aria-haspopup="dialog" aria-label="Share link: Understanding Incremental Backups"> <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>Incremental backups only store changes since the last backup, reducing storage and time.</p> <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">Day 1: Full Backup (10GB) </span></span><span class="line"><span class="cl">Day 2: Incremental (+500MB changes) </span></span><span class="line"><span class="cl">Day 3: Incremental (+300MB changes) </span></span><span class="line"><span class="cl">Day 4: Incremental (+400MB changes) </span></span><span class="line"><span class="cl">... </span></span><span class="line"><span class="cl">Day 7: New Full Backup </span></span></code></pre></div> <h4 id="creating-incremental-backups" class="position-relative d-flex align-items-center group"> <span>Creating Incremental Backups</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="creating-incremental-backups" aria-haspopup="dialog" aria-label="Share link: Creating Incremental Backups"> <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"># Create incremental backup based on last full backup</span> </span></span><span class="line"><span class="cl">geode backup incremental <span class="se">\ </span></span></span><span class="line"><span class="cl"><span class="se"></span> --base /backups/full/geode-full-20260125.backup <span class="se">\ </span></span></span><span class="line"><span class="cl"><span class="se"></span> --output /backups/incremental/geode-incr-<span class="k">$(</span>date +%Y%m%d-%H%M%S<span class="k">)</span>.backup </span></span></code></pre></div><div class="docs-tabs mb-4"> <ul class="nav nav-tabs" id="tabs-1774880883815514356" role="tablist"><li class="nav-item" role="presentation"> <button class="nav-link active" id="tabs-1774880883815514356-tab-0-tab" data-bs-toggle="tab" data-bs-target="#tabs-1774880883815514356-tab-0" type="button" role="tab" aria-controls="tabs-1774880883815514356-tab-0" aria-selected="true" > Python </button> </li><li class="nav-item" role="presentation"> <button class="nav-link" id="tabs-1774880883815514356-tab-1-tab" data-bs-toggle="tab" data-bs-target="#tabs-1774880883815514356-tab-1" type="button" role="tab" aria-controls="tabs-1774880883815514356-tab-1" aria-selected="false" > Go </button> </li></ul> <div class="tab-content border border-top-0 rounded-bottom p-3" id="tabs-1774880883815514356-content"><div class="tab-pane fade show active" id="tabs-1774880883815514356-tab-0" role="tabpanel" aria-labelledby="tabs-1774880883815514356-tab-0-tab" > <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">asyncio</span> </span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">os</span> </span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">json</span> </span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">datetime</span> <span class="kn">import</span> <span class="n">datetime</span> </span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">geode_client</span> <span class="kn">import</span> <span class="n">Client</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">IncrementalBackupManager</span><span class="p">:</span> </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">backup_dir</span><span class="p">:</span> <span class="nb">str</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">backup_dir</span> <span class="o">=</span> <span class="n">backup_dir</span> </span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">full_dir</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">backup_dir</span><span class="p">,</span> <span class="s2">&#34;full&#34;</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">incr_dir</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">backup_dir</span><span class="p">,</span> <span class="s2">&#34;incremental&#34;</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">state_file</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">backup_dir</span><span class="p">,</span> <span class="s2">&#34;backup_state.json&#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">os</span><span class="o">.</span><span class="n">makedirs</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">full_dir</span><span class="p">,</span> <span class="n">exist_ok</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="n">os</span><span class="o">.</span><span class="n">makedirs</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">incr_dir</span><span class="p">,</span> <span class="n">exist_ok</span><span class="o">=</span><span class="kc">True</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">_load_state</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">dict</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">with</span> <span class="nb">open</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">state_file</span><span class="p">,</span> <span class="s1">&#39;r&#39;</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">json</span><span class="o">.</span><span class="n">load</span><span class="p">(</span><span class="n">f</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="k">except</span> <span class="ne">FileNotFoundError</span><span class="p">:</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="p">{</span><span class="s2">&#34;last_full&#34;</span><span class="p">:</span> <span class="kc">None</span><span class="p">,</span> <span class="s2">&#34;last_lsn&#34;</span><span class="p">:</span> <span class="mi">0</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">_save_state</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">state</span><span class="p">:</span> <span class="nb">dict</span><span class="p">):</span> </span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">state_file</span><span class="p">,</span> <span class="s1">&#39;w&#39;</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span> </span></span><span class="line"><span class="cl"> <span class="n">json</span><span class="o">.</span><span class="n">dump</span><span class="p">(</span><span class="n">state</span><span class="p">,</span> <span class="n">f</span><span class="p">,</span> <span class="n">indent</span><span class="o">=</span><span class="mi">2</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">create_full_backup</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">str</span><span class="p">:</span> </span></span><span class="line"><span class="cl"> <span class="s2">&#34;&#34;&#34;Create a new full backup.&#34;&#34;&#34;</span> </span></span><span class="line"><span class="cl"> <span class="n">client</span> <span class="o">=</span> <span class="n">Client</span><span class="p">(</span><span class="n">host</span><span class="o">=</span><span class="s2">&#34;localhost&#34;</span><span class="p">,</span> <span class="n">port</span><span class="o">=</span><span class="mi">3141</span><span class="p">,</span> <span class="n">skip_verify</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="n">timestamp</span> <span class="o">=</span> <span class="n">datetime</span><span class="o">.</span><span class="n">now</span><span class="p">()</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="s2">&#34;%Y%m</span><span class="si">%d</span><span class="s2">-%H%M%S&#34;</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="n">backup_path</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</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">full_dir</span><span class="p">,</span> <span class="sa">f</span><span class="s2">&#34;full-</span><span class="si">{</span><span class="n">timestamp</span><span class="si">}</span><span class="s2">.backup&#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">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"># Create full backup</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></span><span class="line"><span class="cl"> <span class="s2">&#34;&#34;&#34;CALL geode.backup.full($path, { </span></span></span><span class="line"><span class="cl"><span class="s2"> include_metadata: true, </span></span></span><span class="line"><span class="cl"><span class="s2"> compression: &#39;gzip&#39; </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 class="p">{</span><span class="s2">&#34;path&#34;</span><span class="p">:</span> <span class="n">backup_path</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">if</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">lsn</span> <span class="o">=</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="s1">&#39;end_lsn&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">as_int</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="c1"># Update state</span> </span></span><span class="line"><span class="cl"> <span class="n">state</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_load_state</span><span class="p">()</span> </span></span><span class="line"><span class="cl"> <span class="n">state</span><span class="p">[</span><span class="s2">&#34;last_full&#34;</span><span class="p">]</span> <span class="o">=</span> <span class="n">backup_path</span> </span></span><span class="line"><span class="cl"> <span class="n">state</span><span class="p">[</span><span class="s2">&#34;last_lsn&#34;</span><span class="p">]</span> <span class="o">=</span> <span class="n">lsn</span> </span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">_save_state</span><span class="p">(</span><span class="n">state</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="sa">f</span><span class="s2">&#34;Full backup created: </span><span class="si">{</span><span class="n">backup_path</span><span class="si">}</span><span class="s2">&#34;</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; End LSN: </span><span class="si">{</span><span class="n">lsn</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="n">backup_path</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="k">return</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">create_incremental_backup</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">str</span><span class="p">:</span> </span></span><span class="line"><span class="cl"> <span class="s2">&#34;&#34;&#34;Create an incremental backup since last backup.&#34;&#34;&#34;</span> </span></span><span class="line"><span class="cl"> <span class="n">state</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_load_state</span><span class="p">()</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="ow">not</span> <span class="n">state</span><span class="p">[</span><span class="s2">&#34;last_full&#34;</span><span class="p">]:</span> </span></span><span class="line"><span class="cl"> <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;No full backup exists. Creating full backup first...&#34;</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="bp">self</span><span class="o">.</span><span class="n">create_full_backup</span><span class="p">()</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="n">client</span> <span class="o">=</span> <span class="n">Client</span><span class="p">(</span><span class="n">host</span><span class="o">=</span><span class="s2">&#34;localhost&#34;</span><span class="p">,</span> <span class="n">port</span><span class="o">=</span><span class="mi">3141</span><span class="p">,</span> <span class="n">skip_verify</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="n">timestamp</span> <span class="o">=</span> <span class="n">datetime</span><span class="o">.</span><span class="n">now</span><span class="p">()</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="s2">&#34;%Y%m</span><span class="si">%d</span><span class="s2">-%H%M%S&#34;</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="n">backup_path</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</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">incr_dir</span><span class="p">,</span> <span class="sa">f</span><span class="s2">&#34;incr-</span><span class="si">{</span><span class="n">timestamp</span><span class="si">}</span><span class="s2">.backup&#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">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"># Create incremental backup</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></span><span class="line"><span class="cl"> <span class="s2">&#34;&#34;&#34;CALL geode.backup.incremental($path, $from_lsn, { </span></span></span><span class="line"><span class="cl"><span class="s2"> compression: &#39;gzip&#39; </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 class="p">{</span><span class="s2">&#34;path&#34;</span><span class="p">:</span> <span class="n">backup_path</span><span class="p">,</span> <span class="s2">&#34;from_lsn&#34;</span><span class="p">:</span> <span class="n">state</span><span class="p">[</span><span class="s2">&#34;last_lsn&#34;</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">if</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">row</span> <span class="o">=</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></span><span class="line"><span class="cl"> <span class="n">changes</span> <span class="o">=</span> <span class="n">row</span><span class="p">[</span><span class="s1">&#39;change_count&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">as_int</span> </span></span><span class="line"><span class="cl"> <span class="n">end_lsn</span> <span class="o">=</span> <span class="n">row</span><span class="p">[</span><span class="s1">&#39;end_lsn&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">as_int</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">changes</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span> </span></span><span class="line"><span class="cl"> <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;No changes since last backup&#34;</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="n">os</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">backup_path</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="kc">None</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="c1"># Update state</span> </span></span><span class="line"><span class="cl"> <span class="n">state</span><span class="p">[</span><span class="s2">&#34;last_lsn&#34;</span><span class="p">]</span> <span class="o">=</span> <span class="n">end_lsn</span> </span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">_save_state</span><span class="p">(</span><span class="n">state</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="sa">f</span><span class="s2">&#34;Incremental backup created: </span><span class="si">{</span><span class="n">backup_path</span><span class="si">}</span><span class="s2">&#34;</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; Changes: </span><span class="si">{</span><span class="n">changes</span><span class="si">:</span><span class="s2">,</span><span class="si">}</span><span class="s2">&#34;</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; End LSN: </span><span class="si">{</span><span class="n">end_lsn</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="n">backup_path</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="k">return</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">main</span><span class="p">():</span> </span></span><span class="line"><span class="cl"> <span class="n">manager</span> <span class="o">=</span> <span class="n">IncrementalBackupManager</span><span class="p">(</span><span class="s2">&#34;/backups/geode&#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"># Weekly: Create full backup</span> </span></span><span class="line"><span class="cl"> <span class="c1"># await manager.create_full_backup()</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="c1"># Daily: Create incremental backup</span> </span></span><span class="line"><span class="cl"> <span class="k">await</span> <span class="n">manager</span><span class="o">.</span><span class="n">create_incremental_backup</span><span class="p">()</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="n">asyncio</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="n">main</span><span class="p">())</span> </span></span></code></pre></div> </div><div class="tab-pane fade" id="tabs-1774880883815514356-tab-1" role="tabpanel" aria-labelledby="tabs-1774880883815514356-tab-1-tab" > <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;encoding/json&#34;</span> </span></span><span class="line"><span class="cl"> <span class="s">&#34;fmt&#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 class="s">&#34;os&#34;</span> </span></span><span class="line"><span class="cl"> <span class="s">&#34;path/filepath&#34;</span> </span></span><span class="line"><span class="cl"> <span class="s">&#34;time&#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">BackupState</span> <span class="kd">struct</span> <span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">LastFull</span> <span class="kt">string</span> <span class="s">`json:&#34;last_full&#34;`</span> </span></span><span class="line"><span class="cl"> <span class="nx">LastLSN</span> <span class="kt">int64</span> <span class="s">`json:&#34;last_lsn&#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">IncrementalBackupManager</span> <span class="kd">struct</span> <span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">backupDir</span> <span class="kt">string</span> </span></span><span class="line"><span class="cl"> <span class="nx">db</span> <span class="o">*</span><span class="nx">sql</span><span class="p">.</span><span class="nx">DB</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">NewIncrementalBackupManager</span><span class="p">(</span><span class="nx">backupDir</span> <span class="kt">string</span><span class="p">,</span> <span class="nx">db</span> <span class="o">*</span><span class="nx">sql</span><span class="p">.</span><span class="nx">DB</span><span class="p">)</span> <span class="o">*</span><span class="nx">IncrementalBackupManager</span> <span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">os</span><span class="p">.</span><span class="nf">MkdirAll</span><span class="p">(</span><span class="nx">filepath</span><span class="p">.</span><span class="nf">Join</span><span class="p">(</span><span class="nx">backupDir</span><span class="p">,</span> <span class="s">&#34;full&#34;</span><span class="p">),</span> <span class="mo">0755</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="nx">os</span><span class="p">.</span><span class="nf">MkdirAll</span><span class="p">(</span><span class="nx">filepath</span><span class="p">.</span><span class="nf">Join</span><span class="p">(</span><span class="nx">backupDir</span><span class="p">,</span> <span class="s">&#34;incremental&#34;</span><span class="p">),</span> <span class="mo">0755</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="o">&amp;</span><span class="nx">IncrementalBackupManager</span><span class="p">{</span><span class="nx">backupDir</span><span class="p">:</span> <span class="nx">backupDir</span><span class="p">,</span> <span class="nx">db</span><span class="p">:</span> <span class="nx">db</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="p">(</span><span class="nx">m</span> <span class="o">*</span><span class="nx">IncrementalBackupManager</span><span class="p">)</span> <span class="nf">loadState</span><span class="p">()</span> <span class="nx">BackupState</span> <span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">stateFile</span> <span class="o">:=</span> <span class="nx">filepath</span><span class="p">.</span><span class="nf">Join</span><span class="p">(</span><span class="nx">m</span><span class="p">.</span><span class="nx">backupDir</span><span class="p">,</span> <span class="s">&#34;backup_state.json&#34;</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="nx">data</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">os</span><span class="p">.</span><span class="nf">ReadFile</span><span class="p">(</span><span class="nx">stateFile</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="nx">BackupState</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="kd">var</span> <span class="nx">state</span> <span class="nx">BackupState</span> </span></span><span class="line"><span class="cl"> <span class="nx">json</span><span class="p">.</span><span class="nf">Unmarshal</span><span class="p">(</span><span class="nx">data</span><span class="p">,</span> <span class="o">&amp;</span><span class="nx">state</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nx">state</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="p">(</span><span class="nx">m</span> <span class="o">*</span><span class="nx">IncrementalBackupManager</span><span class="p">)</span> <span class="nf">saveState</span><span class="p">(</span><span class="nx">state</span> <span class="nx">BackupState</span><span class="p">)</span> <span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">stateFile</span> <span class="o">:=</span> <span class="nx">filepath</span><span class="p">.</span><span class="nf">Join</span><span class="p">(</span><span class="nx">m</span><span class="p">.</span><span class="nx">backupDir</span><span class="p">,</span> <span class="s">&#34;backup_state.json&#34;</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="nx">data</span><span class="p">,</span> <span class="nx">_</span> <span class="o">:=</span> <span class="nx">json</span><span class="p">.</span><span class="nf">MarshalIndent</span><span class="p">(</span><span class="nx">state</span><span class="p">,</span> <span class="s">&#34;&#34;</span><span class="p">,</span> <span class="s">&#34; &#34;</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="nx">os</span><span class="p">.</span><span class="nf">WriteFile</span><span class="p">(</span><span class="nx">stateFile</span><span class="p">,</span> <span class="nx">data</span><span class="p">,</span> <span class="mo">0644</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="p">(</span><span class="nx">m</span> <span class="o">*</span><span class="nx">IncrementalBackupManager</span><span class="p">)</span> <span class="nf">CreateFullBackup</span><span class="p">(</span><span class="nx">ctx</span> <span class="nx">context</span><span class="p">.</span><span class="nx">Context</span><span class="p">)</span> <span class="p">(</span><span class="kt">string</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">timestamp</span> <span class="o">:=</span> <span class="nx">time</span><span class="p">.</span><span class="nf">Now</span><span class="p">().</span><span class="nf">Format</span><span class="p">(</span><span class="s">&#34;20060102-150405&#34;</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="nx">backupPath</span> <span class="o">:=</span> <span class="nx">filepath</span><span class="p">.</span><span class="nf">Join</span><span class="p">(</span><span class="nx">m</span><span class="p">.</span><span class="nx">backupDir</span><span class="p">,</span> <span class="s">&#34;full&#34;</span><span class="p">,</span> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Sprintf</span><span class="p">(</span><span class="s">&#34;full-%s.backup&#34;</span><span class="p">,</span> <span class="nx">timestamp</span><span class="p">))</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">m</span><span class="p">.</span><span class="nx">db</span><span class="p">.</span><span class="nf">QueryContext</span><span class="p">(</span><span class="nx">ctx</span><span class="p">,</span> <span class="s">` </span></span></span><span class="line"><span class="cl"><span class="s"> CALL geode.backup.full($1, {include_metadata: true, compression: &#39;gzip&#39;}) </span></span></span><span class="line"><span class="cl"><span class="s"> `</span><span class="p">,</span> <span class="nx">backupPath</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="s">&#34;&#34;</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="k">if</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">endLSN</span> <span class="kt">int64</span> </span></span><span class="line"><span class="cl"> <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">endLSN</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="nx">state</span> <span class="o">:=</span> <span class="nx">BackupState</span><span class="p">{</span><span class="nx">LastFull</span><span class="p">:</span> <span class="nx">backupPath</span><span class="p">,</span> <span class="nx">LastLSN</span><span class="p">:</span> <span class="nx">endLSN</span><span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="nx">m</span><span class="p">.</span><span class="nf">saveState</span><span class="p">(</span><span class="nx">state</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> </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;Full backup created: %s (LSN: %d)&#34;</span><span class="p">,</span> <span class="nx">backupPath</span><span class="p">,</span> <span class="nx">endLSN</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nx">backupPath</span><span class="p">,</span> <span class="kc">nil</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="s">&#34;&#34;</span><span class="p">,</span> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Errorf</span><span class="p">(</span><span class="s">&#34;backup failed&#34;</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="p">(</span><span class="nx">m</span> <span class="o">*</span><span class="nx">IncrementalBackupManager</span><span class="p">)</span> <span class="nf">CreateIncrementalBackup</span><span class="p">(</span><span class="nx">ctx</span> <span class="nx">context</span><span class="p">.</span><span class="nx">Context</span><span class="p">)</span> <span class="p">(</span><span class="kt">string</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">state</span> <span class="o">:=</span> <span class="nx">m</span><span class="p">.</span><span class="nf">loadState</span><span class="p">()</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nx">state</span><span class="p">.</span><span class="nx">LastFull</span> <span class="o">==</span> <span class="s">&#34;&#34;</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">Println</span><span class="p">(</span><span class="s">&#34;No full backup exists, creating one first...&#34;</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nx">m</span><span class="p">.</span><span class="nf">CreateFullBackup</span><span class="p">(</span><span class="nx">ctx</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="nx">timestamp</span> <span class="o">:=</span> <span class="nx">time</span><span class="p">.</span><span class="nf">Now</span><span class="p">().</span><span class="nf">Format</span><span class="p">(</span><span class="s">&#34;20060102-150405&#34;</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="nx">backupPath</span> <span class="o">:=</span> <span class="nx">filepath</span><span class="p">.</span><span class="nf">Join</span><span class="p">(</span><span class="nx">m</span><span class="p">.</span><span class="nx">backupDir</span><span class="p">,</span> <span class="s">&#34;incremental&#34;</span><span class="p">,</span> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Sprintf</span><span class="p">(</span><span class="s">&#34;incr-%s.backup&#34;</span><span class="p">,</span> <span class="nx">timestamp</span><span class="p">))</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">m</span><span class="p">.</span><span class="nx">db</span><span class="p">.</span><span class="nf">QueryContext</span><span class="p">(</span><span class="nx">ctx</span><span class="p">,</span> <span class="s">` </span></span></span><span class="line"><span class="cl"><span class="s"> CALL geode.backup.incremental($1, $2, {compression: &#39;gzip&#39;}) </span></span></span><span class="line"><span class="cl"><span class="s"> `</span><span class="p">,</span> <span class="nx">backupPath</span><span class="p">,</span> <span class="nx">state</span><span class="p">.</span><span class="nx">LastLSN</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="s">&#34;&#34;</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="k">if</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">changes</span> <span class="kt">int64</span> </span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">endLSN</span> <span class="kt">int64</span> </span></span><span class="line"><span class="cl"> <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">changes</span><span class="p">,</span> <span class="o">&amp;</span><span class="nx">endLSN</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nx">changes</span> <span class="o">==</span> <span class="mi">0</span> <span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="nx">os</span><span class="p">.</span><span class="nf">Remove</span><span class="p">(</span><span class="nx">backupPath</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">Println</span><span class="p">(</span><span class="s">&#34;No changes since last backup&#34;</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="s">&#34;&#34;</span><span class="p">,</span> <span class="kc">nil</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="nx">state</span><span class="p">.</span><span class="nx">LastLSN</span> <span class="p">=</span> <span class="nx">endLSN</span> </span></span><span class="line"><span class="cl"> <span class="nx">m</span><span class="p">.</span><span class="nf">saveState</span><span class="p">(</span><span class="nx">state</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> </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;Incremental backup: %s (changes: %d, LSN: %d)&#34;</span><span class="p">,</span> <span class="nx">backupPath</span><span class="p">,</span> <span class="nx">changes</span><span class="p">,</span> <span class="nx">endLSN</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nx">backupPath</span><span class="p">,</span> <span class="kc">nil</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="s">&#34;&#34;</span><span class="p">,</span> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Errorf</span><span class="p">(</span><span class="s">&#34;incremental backup failed&#34;</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">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;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="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 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">ctx</span> <span class="o">:=</span> <span class="nx">context</span><span class="p">.</span><span class="nf">Background</span><span class="p">()</span> </span></span><span class="line"><span class="cl"> <span class="nx">manager</span> <span class="o">:=</span> <span class="nf">NewIncrementalBackupManager</span><span class="p">(</span><span class="s">&#34;/backups/geode&#34;</span><span class="p">,</span> <span class="nx">db</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="c1">// Create incremental backup </span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">_</span><span class="p">,</span> <span class="nx">err</span> <span class="p">=</span> <span class="nx">manager</span><span class="p">.</span><span class="nf">CreateIncrementalBackup</span><span class="p">(</span><span class="nx">ctx</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">Fatalf</span><span class="p">(</span><span class="s">&#34;Backup failed: %v&#34;</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 class="p">}</span> </span></span></code></pre></div> </div></div> </div> <h3 id="point-in-time-recovery" class="position-relative d-flex align-items-center group"> <span>Point-in-Time Recovery</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="point-in-time-recovery" aria-haspopup="dialog" aria-label="Share link: Point-in-Time Recovery"> <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="understanding-pitr" class="position-relative d-flex align-items-center group"> <span>Understanding PITR</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="understanding-pitr" aria-haspopup="dialog" aria-label="Share link: Understanding PITR"> <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>Point-in-Time Recovery allows you to restore the database to any specific moment.</p> <p><strong>Requirements</strong>:</p> <ul> <li>Full backup as a base</li> <li>Continuous WAL (Write-Ahead Log) archiving</li> <li>WAL files stored safely</li> </ul> <h4 id="configuring-wal-archiving" class="position-relative d-flex align-items-center group"> <span>Configuring WAL Archiving</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="configuring-wal-archiving" aria-haspopup="dialog" aria-label="Share link: Configuring WAL Archiving"> <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>geode.conf</strong>:</p> <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-toml" data-lang="toml"><span class="line"><span class="cl"><span class="p">[</span><span class="nx">wal</span><span class="p">]</span> </span></span><span class="line"><span class="cl"><span class="nx">archive_enabled</span> <span class="p">=</span> <span class="kc">true</span> </span></span><span class="line"><span class="cl"><span class="nx">archive_command</span> <span class="p">=</span> <span class="s2">&#34;cp %p /backups/wal/%f&#34;</span> </span></span><span class="line"><span class="cl"><span class="nx">archive_timeout</span> <span class="p">=</span> <span class="mi">60</span> <span class="c"># seconds</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="p">[</span><span class="nx">recovery</span><span class="p">]</span> </span></span><span class="line"><span class="cl"><span class="nx">restore_command</span> <span class="p">=</span> <span class="s2">&#34;cp /backups/wal/%f %p&#34;</span> </span></span></code></pre></div> <h4 id="performing-point-in-time-recovery" class="position-relative d-flex align-items-center group"> <span>Performing Point-in-Time Recovery</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="performing-point-in-time-recovery" aria-haspopup="dialog" aria-label="Share link: Performing Point-in-Time Recovery"> <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"># Restore to specific timestamp</span> </span></span><span class="line"><span class="cl">geode restore <span class="se">\ </span></span></span><span class="line"><span class="cl"><span class="se"></span> --backup /backups/full/geode-full-20260125.backup <span class="se">\ </span></span></span><span class="line"><span class="cl"><span class="se"></span> --wal-dir /backups/wal <span class="se">\ </span></span></span><span class="line"><span class="cl"><span class="se"></span> --target-time <span class="s2">&#34;2026-01-28T14:30:00Z&#34;</span> <span class="se">\ </span></span></span><span class="line"><span class="cl"><span class="se"></span> --output /var/lib/geode/data </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="c1"># Restore to specific transaction</span> </span></span><span class="line"><span class="cl">geode restore <span class="se">\ </span></span></span><span class="line"><span class="cl"><span class="se"></span> --backup /backups/full/geode-full-20260125.backup <span class="se">\ </span></span></span><span class="line"><span class="cl"><span class="se"></span> --wal-dir /backups/wal <span class="se">\ </span></span></span><span class="line"><span class="cl"><span class="se"></span> --target-lsn <span class="m">12345678</span> <span class="se">\ </span></span></span><span class="line"><span class="cl"><span class="se"></span> --output /var/lib/geode/data </span></span></code></pre></div><div class="docs-tabs mb-4"> <ul class="nav nav-tabs" id="tabs-1774880883839918913" role="tablist"><li class="nav-item" role="presentation"> <button class="nav-link active" id="tabs-1774880883839918913-tab-0-tab" data-bs-toggle="tab" data-bs-target="#tabs-1774880883839918913-tab-0" type="button" role="tab" aria-controls="tabs-1774880883839918913-tab-0" aria-selected="true" > Python </button> </li></ul> <div class="tab-content border border-top-0 rounded-bottom p-3" id="tabs-1774880883839918913-content"><div class="tab-pane fade show active" id="tabs-1774880883839918913-tab-0" role="tabpanel" aria-labelledby="tabs-1774880883839918913-tab-0-tab" > <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">asyncio</span> </span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">datetime</span> <span class="kn">import</span> <span class="n">datetime</span> </span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">geode_client</span> <span class="kn">import</span> <span class="n">Client</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">point_in_time_recovery</span><span class="p">(</span> </span></span><span class="line"><span class="cl"> <span class="n">backup_path</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> </span></span><span class="line"><span class="cl"> <span class="n">wal_dir</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> </span></span><span class="line"><span class="cl"> <span class="n">target_time</span><span class="p">:</span> <span class="n">datetime</span><span class="p">,</span> </span></span><span class="line"><span class="cl"> <span class="n">output_dir</span><span class="p">:</span> <span class="nb">str</span> </span></span><span class="line"><span class="cl"><span class="p">):</span> </span></span><span class="line"><span class="cl"> <span class="s2">&#34;&#34;&#34;Restore database to a specific point in time.&#34;&#34;&#34;</span> </span></span><span class="line"><span class="cl"> <span class="n">client</span> <span class="o">=</span> <span class="n">Client</span><span class="p">(</span><span class="n">host</span><span class="o">=</span><span class="s2">&#34;localhost&#34;</span><span class="p">,</span> <span class="n">port</span><span class="o">=</span><span class="mi">3141</span><span class="p">,</span> <span class="n">skip_verify</span><span class="o">=</span><span class="kc">True</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">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="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;Starting point-in-time recovery...&#34;</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; Base backup: </span><span class="si">{</span><span class="n">backup_path</span><span class="si">}</span><span class="s2">&#34;</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; Target time: </span><span class="si">{</span><span class="n">target_time</span><span class="o">.</span><span class="n">isoformat</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></span><span class="line"><span class="cl"> <span class="c1"># Initiate PITR</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></span><span class="line"><span class="cl"> <span class="s2">&#34;&#34;&#34;CALL geode.restore.point_in_time($backup, $wal_dir, $target, $output, { </span></span></span><span class="line"><span class="cl"><span class="s2"> verify: true, </span></span></span><span class="line"><span class="cl"><span class="s2"> create_recovery_conf: true </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 class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="s2">&#34;backup&#34;</span><span class="p">:</span> <span class="n">backup_path</span><span class="p">,</span> </span></span><span class="line"><span class="cl"> <span class="s2">&#34;wal_dir&#34;</span><span class="p">:</span> <span class="n">wal_dir</span><span class="p">,</span> </span></span><span class="line"><span class="cl"> <span class="s2">&#34;target&#34;</span><span class="p">:</span> <span class="n">target_time</span><span class="o">.</span><span class="n">isoformat</span><span class="p">(),</span> </span></span><span class="line"><span class="cl"> <span class="s2">&#34;output&#34;</span><span class="p">:</span> <span class="n">output_dir</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">if</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">info</span> <span class="o">=</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></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;Recovery complete:&#34;</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; Restored to: </span><span class="si">{</span><span class="n">info</span><span class="p">[</span><span class="s1">&#39;restored_to&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">as_string</span><span class="si">}</span><span class="s2">&#34;</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; WAL files applied: </span><span class="si">{</span><span class="n">info</span><span class="p">[</span><span class="s1">&#39;wal_files_applied&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">as_int</span><span class="si">}</span><span class="s2">&#34;</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; Transactions recovered: </span><span class="si">{</span><span class="n">info</span><span class="p">[</span><span class="s1">&#39;transactions_recovered&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">as_int</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="kc">True</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="kc">False</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">main</span><span class="p">():</span> </span></span><span class="line"><span class="cl"> <span class="c1"># Restore to 2:30 PM today</span> </span></span><span class="line"><span class="cl"> <span class="n">target</span> <span class="o">=</span> <span class="n">datetime</span><span class="p">(</span><span class="mi">2026</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">28</span><span class="p">,</span> <span class="mi">14</span><span class="p">,</span> <span class="mi">30</span><span class="p">,</span> <span class="mi">0</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">point_in_time_recovery</span><span class="p">(</span> </span></span><span class="line"><span class="cl"> <span class="n">backup_path</span><span class="o">=</span><span class="s2">&#34;/backups/full/geode-full-20260125.backup&#34;</span><span class="p">,</span> </span></span><span class="line"><span class="cl"> <span class="n">wal_dir</span><span class="o">=</span><span class="s2">&#34;/backups/wal&#34;</span><span class="p">,</span> </span></span><span class="line"><span class="cl"> <span class="n">target_time</span><span class="o">=</span><span class="n">target</span><span class="p">,</span> </span></span><span class="line"><span class="cl"> <span class="n">output_dir</span><span class="o">=</span><span class="s2">&#34;/var/lib/geode/data-recovered&#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="n">asyncio</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="n">main</span><span class="p">())</span> </span></span></code></pre></div> </div></div> </div> <h3 id="backup-verification" class="position-relative d-flex align-items-center group"> <span>Backup Verification</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="backup-verification" aria-haspopup="dialog" aria-label="Share link: Backup Verification"> <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="automatic-verification" class="position-relative d-flex align-items-center group"> <span>Automatic Verification</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="automatic-verification" aria-haspopup="dialog" aria-label="Share link: Automatic Verification"> <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"># Verify backup integrity</span> </span></span><span class="line"><span class="cl">geode backup verify /backups/geode-20260128.backup </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="c1"># Verify with detailed output</span> </span></span><span class="line"><span class="cl">geode backup verify <span class="se">\ </span></span></span><span class="line"><span class="cl"><span class="se"></span> --backup /backups/geode-20260128.backup <span class="se">\ </span></span></span><span class="line"><span class="cl"><span class="se"></span> --check-checksums <span class="se">\ </span></span></span><span class="line"><span class="cl"><span class="se"></span> --check-consistency <span class="se">\ </span></span></span><span class="line"><span class="cl"><span class="se"></span> --verbose </span></span></code></pre></div> <h4 id="programmatic-verification" class="position-relative d-flex align-items-center group"> <span>Programmatic Verification</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="programmatic-verification" aria-haspopup="dialog" aria-label="Share link: Programmatic Verification"> <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="docs-tabs mb-4"> <ul class="nav nav-tabs" id="tabs-1774880883845372487" role="tablist"><li class="nav-item" role="presentation"> <button class="nav-link active" id="tabs-1774880883845372487-tab-0-tab" data-bs-toggle="tab" data-bs-target="#tabs-1774880883845372487-tab-0" type="button" role="tab" aria-controls="tabs-1774880883845372487-tab-0" aria-selected="true" > Python </button> </li></ul> <div class="tab-content border border-top-0 rounded-bottom p-3" id="tabs-1774880883845372487-content"><div class="tab-pane fade show active" id="tabs-1774880883845372487-tab-0" role="tabpanel" aria-labelledby="tabs-1774880883845372487-tab-0-tab" > <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">asyncio</span> </span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">geode_client</span> <span class="kn">import</span> <span class="n">Client</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">verify_backup</span><span class="p">(</span><span class="n">backup_path</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">bool</span><span class="p">:</span> </span></span><span class="line"><span class="cl"> <span class="s2">&#34;&#34;&#34;Comprehensively verify a backup file.&#34;&#34;&#34;</span> </span></span><span class="line"><span class="cl"> <span class="n">client</span> <span class="o">=</span> <span class="n">Client</span><span class="p">(</span><span class="n">host</span><span class="o">=</span><span class="s2">&#34;localhost&#34;</span><span class="p">,</span> <span class="n">port</span><span class="o">=</span><span class="mi">3141</span><span class="p">,</span> <span class="n">skip_verify</span><span class="o">=</span><span class="kc">True</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">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="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;Verifying backup: </span><span class="si">{</span><span class="n">backup_path</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"># Basic integrity check</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></span><span class="line"><span class="cl"> <span class="s2">&#34;&#34;&#34;CALL geode.backup.verify($path, { </span></span></span><span class="line"><span class="cl"><span class="s2"> check_checksums: true, </span></span></span><span class="line"><span class="cl"><span class="s2"> check_consistency: true, </span></span></span><span class="line"><span class="cl"><span class="s2"> check_indexes: true </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 class="p">{</span><span class="s2">&#34;path&#34;</span><span class="p">:</span> <span class="n">backup_path</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">if</span> <span class="ow">not</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="nb">print</span><span class="p">(</span><span class="s2">&#34;Verification failed: No result&#34;</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="kc">False</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="n">info</span> <span class="o">=</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></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="n">checks</span> <span class="o">=</span> <span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="s2">&#34;File integrity&#34;</span><span class="p">:</span> <span class="n">info</span><span class="p">[</span><span class="s1">&#39;file_valid&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">as_bool</span><span class="p">,</span> </span></span><span class="line"><span class="cl"> <span class="s2">&#34;Checksum match&#34;</span><span class="p">:</span> <span class="n">info</span><span class="p">[</span><span class="s1">&#39;checksum_valid&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">as_bool</span><span class="p">,</span> </span></span><span class="line"><span class="cl"> <span class="s2">&#34;Data consistency&#34;</span><span class="p">:</span> <span class="n">info</span><span class="p">[</span><span class="s1">&#39;data_consistent&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">as_bool</span><span class="p">,</span> </span></span><span class="line"><span class="cl"> <span class="s2">&#34;Index integrity&#34;</span><span class="p">:</span> <span class="n">info</span><span class="p">[</span><span class="s1">&#39;indexes_valid&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">as_bool</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">all_passed</span> <span class="o">=</span> <span class="kc">True</span> </span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">check_name</span><span class="p">,</span> <span class="n">passed</span> <span class="ow">in</span> <span class="n">checks</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">status</span> <span class="o">=</span> <span class="s2">&#34;PASS&#34;</span> <span class="k">if</span> <span class="n">passed</span> <span class="k">else</span> <span class="s2">&#34;FAIL&#34;</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">check_name</span><span class="si">}</span><span class="s2">: </span><span class="si">{</span><span class="n">status</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">if</span> <span class="ow">not</span> <span class="n">passed</span><span class="p">:</span> </span></span><span class="line"><span class="cl"> <span class="n">all_passed</span> <span class="o">=</span> <span class="kc">False</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">all_passed</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="se">\n</span><span class="s2">Backup verification: PASSED&#34;</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; Checksum: </span><span class="si">{</span><span class="n">info</span><span class="p">[</span><span class="s1">&#39;checksum&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">as_string</span><span class="si">}</span><span class="s2">&#34;</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; Node count: </span><span class="si">{</span><span class="n">info</span><span class="p">[</span><span class="s1">&#39;node_count&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">as_int</span><span class="si">:</span><span class="s2">,</span><span class="si">}</span><span class="s2">&#34;</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; Relationship count: </span><span class="si">{</span><span class="n">info</span><span class="p">[</span><span class="s1">&#39;relationship_count&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">as_int</span><span class="si">:</span><span class="s2">,</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="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;</span><span class="se">\n</span><span class="s2">Backup verification: FAILED&#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="n">all_passed</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">verify_all_backups</span><span class="p">(</span><span class="n">backup_dir</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;Verify all backups in a directory.&#34;&#34;&#34;</span> </span></span><span class="line"><span class="cl"> <span class="kn">import</span> <span class="nn">os</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="n">results</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">filename</span> <span class="ow">in</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">backup_dir</span><span class="p">):</span> </span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">filename</span><span class="o">.</span><span class="n">endswith</span><span class="p">(</span><span class="s1">&#39;.backup&#39;</span><span class="p">):</span> </span></span><span class="line"><span class="cl"> <span class="n">path</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">backup_dir</span><span class="p">,</span> <span class="n">filename</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="n">valid</span> <span class="o">=</span> <span class="k">await</span> <span class="n">verify_backup</span><span class="p">(</span><span class="n">path</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="n">results</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">filename</span><span class="p">,</span> <span class="n">valid</span><span class="p">))</span> </span></span><span class="line"><span class="cl"> <span class="nb">print</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="s2">&#34;=&#34;</span> <span class="o">*</span> <span class="mi">50</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;SUMMARY&#34;</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;=&#34;</span> <span class="o">*</span> <span class="mi">50</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">filename</span><span class="p">,</span> <span class="n">valid</span> <span class="ow">in</span> <span class="n">results</span><span class="p">:</span> </span></span><span class="line"><span class="cl"> <span class="n">status</span> <span class="o">=</span> <span class="s2">&#34;OK&#34;</span> <span class="k">if</span> <span class="n">valid</span> <span class="k">else</span> <span class="s2">&#34;FAILED&#34;</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">filename</span><span class="si">}</span><span class="s2">: </span><span class="si">{</span><span class="n">status</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="n">asyncio</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="n">verify_all_backups</span><span class="p">(</span><span class="s2">&#34;/backups/full&#34;</span><span class="p">))</span> </span></span></code></pre></div> </div></div> </div> <h4 id="test-restores" class="position-relative d-flex align-items-center group"> <span>Test Restores</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="test-restores" aria-haspopup="dialog" aria-label="Share link: Test Restores"> <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>Regularly test your backups by performing test restores:</p> <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="cp">#!/bin/bash </span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="c1"># Test restore script</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="nv">BACKUP_FILE</span><span class="o">=</span><span class="s2">&#34;</span><span class="nv">$1</span><span class="s2">&#34;</span> </span></span><span class="line"><span class="cl"><span class="nv">TEST_DIR</span><span class="o">=</span><span class="s2">&#34;/tmp/geode-test-restore&#34;</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="c1"># Clean up previous test</span> </span></span><span class="line"><span class="cl">rm -rf <span class="s2">&#34;</span><span class="si">${</span><span class="nv">TEST_DIR</span><span class="si">}</span><span class="s2">&#34;</span> </span></span><span class="line"><span class="cl">mkdir -p <span class="s2">&#34;</span><span class="si">${</span><span class="nv">TEST_DIR</span><span class="si">}</span><span class="s2">&#34;</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="c1"># Restore to test directory</span> </span></span><span class="line"><span class="cl">geode restore <span class="se">\ </span></span></span><span class="line"><span class="cl"><span class="se"></span> --backup <span class="s2">&#34;</span><span class="si">${</span><span class="nv">BACKUP_FILE</span><span class="si">}</span><span class="s2">&#34;</span> <span class="se">\ </span></span></span><span class="line"><span class="cl"><span class="se"></span> --output <span class="s2">&#34;</span><span class="si">${</span><span class="nv">TEST_DIR</span><span class="si">}</span><span class="s2">&#34;</span> <span class="se">\ </span></span></span><span class="line"><span class="cl"><span class="se"></span> --no-start </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="c1"># Verify data</span> </span></span><span class="line"><span class="cl">geode verify <span class="s2">&#34;</span><span class="si">${</span><span class="nv">TEST_DIR</span><span class="si">}</span><span class="s2">&#34;</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="c1"># Start test instance</span> </span></span><span class="line"><span class="cl">geode serve <span class="se">\ </span></span></span><span class="line"><span class="cl"><span class="se"></span> --data-dir <span class="s2">&#34;</span><span class="si">${</span><span class="nv">TEST_DIR</span><span class="si">}</span><span class="s2">&#34;</span> <span class="se">\ </span></span></span><span class="line"><span class="cl"><span class="se"></span> --port <span class="m">3142</span> <span class="p">&amp;</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="nv">GEODE_PID</span><span class="o">=</span><span class="nv">$!</span> </span></span><span class="line"><span class="cl">sleep <span class="m">5</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="c1"># Run verification queries</span> </span></span><span class="line"><span class="cl">geode shell --port <span class="m">3142</span> -c <span class="s2">&#34;MATCH (n) RETURN count(n)&#34;</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="c1"># Stop test instance</span> </span></span><span class="line"><span class="cl"><span class="nb">kill</span> <span class="si">${</span><span class="nv">GEODE_PID</span><span class="si">}</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="c1"># Clean up</span> </span></span><span class="line"><span class="cl">rm -rf <span class="s2">&#34;</span><span class="si">${</span><span class="nv">TEST_DIR</span><span class="si">}</span><span class="s2">&#34;</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;Test restore completed successfully&#34;</span> </span></span></code></pre></div> <h3 id="restore-procedures" class="position-relative d-flex align-items-center group"> <span>Restore Procedures</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="restore-procedures" aria-haspopup="dialog" aria-label="Share link: Restore Procedures"> <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="full-restore" class="position-relative d-flex align-items-center group"> <span>Full Restore</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="full-restore" aria-haspopup="dialog" aria-label="Share link: Full Restore"> <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"># Stop Geode</span> </span></span><span class="line"><span class="cl">systemctl stop geode </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="c1"># Restore from backup</span> </span></span><span class="line"><span class="cl">geode restore <span class="se">\ </span></span></span><span class="line"><span class="cl"><span class="se"></span> --backup /backups/geode-full-20260128.backup <span class="se">\ </span></span></span><span class="line"><span class="cl"><span class="se"></span> --output /var/lib/geode/data <span class="se">\ </span></span></span><span class="line"><span class="cl"><span class="se"></span> --overwrite </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="c1"># Verify restored data</span> </span></span><span class="line"><span class="cl">geode verify /var/lib/geode/data </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="c1"># Start Geode</span> </span></span><span class="line"><span class="cl">systemctl start geode </span></span></code></pre></div> <h4 id="restore-from-incremental-backups" class="position-relative d-flex align-items-center group"> <span>Restore from Incremental Backups</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="restore-from-incremental-backups" aria-haspopup="dialog" aria-label="Share link: Restore from Incremental Backups"> <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"># Restore full backup first</span> </span></span><span class="line"><span class="cl">geode restore <span class="se">\ </span></span></span><span class="line"><span class="cl"><span class="se"></span> --backup /backups/full/geode-full-20260125.backup <span class="se">\ </span></span></span><span class="line"><span class="cl"><span class="se"></span> --output /var/lib/geode/data </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="c1"># Apply incremental backups in order</span> </span></span><span class="line"><span class="cl">geode restore <span class="se">\ </span></span></span><span class="line"><span class="cl"><span class="se"></span> --backup /backups/incremental/geode-incr-20260126.backup <span class="se">\ </span></span></span><span class="line"><span class="cl"><span class="se"></span> --output /var/lib/geode/data <span class="se">\ </span></span></span><span class="line"><span class="cl"><span class="se"></span> --incremental </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl">geode restore <span class="se">\ </span></span></span><span class="line"><span class="cl"><span class="se"></span> --backup /backups/incremental/geode-incr-20260127.backup <span class="se">\ </span></span></span><span class="line"><span class="cl"><span class="se"></span> --output /var/lib/geode/data <span class="se">\ </span></span></span><span class="line"><span class="cl"><span class="se"></span> --incremental </span></span></code></pre></div> <h4 id="programmatic-restore" class="position-relative d-flex align-items-center group"> <span>Programmatic Restore</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="programmatic-restore" aria-haspopup="dialog" aria-label="Share link: Programmatic Restore"> <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="docs-tabs mb-4"> <ul class="nav nav-tabs" id="tabs-1774880883853612658" role="tablist"><li class="nav-item" role="presentation"> <button class="nav-link active" id="tabs-1774880883853612658-tab-0-tab" data-bs-toggle="tab" data-bs-target="#tabs-1774880883853612658-tab-0" type="button" role="tab" aria-controls="tabs-1774880883853612658-tab-0" aria-selected="true" > Python </button> </li></ul> <div class="tab-content border border-top-0 rounded-bottom p-3" id="tabs-1774880883853612658-content"><div class="tab-pane fade show active" id="tabs-1774880883853612658-tab-0" role="tabpanel" aria-labelledby="tabs-1774880883853612658-tab-0-tab" > <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">asyncio</span> </span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">os</span> </span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">geode_client</span> <span class="kn">import</span> <span class="n">Client</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">restore_database</span><span class="p">(</span> </span></span><span class="line"><span class="cl"> <span class="n">backup_path</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> </span></span><span class="line"><span class="cl"> <span class="n">output_dir</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> </span></span><span class="line"><span class="cl"> <span class="n">incremental_backups</span><span class="p">:</span> <span class="nb">list</span> <span class="o">=</span> <span class="kc">None</span> </span></span><span class="line"><span class="cl"><span class="p">):</span> </span></span><span class="line"><span class="cl"> <span class="s2">&#34;&#34;&#34;Restore database from backup files.&#34;&#34;&#34;</span> </span></span><span class="line"><span class="cl"> <span class="n">client</span> <span class="o">=</span> <span class="n">Client</span><span class="p">(</span><span class="n">host</span><span class="o">=</span><span class="s2">&#34;localhost&#34;</span><span class="p">,</span> <span class="n">port</span><span class="o">=</span><span class="mi">3141</span><span class="p">,</span> <span class="n">skip_verify</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="c1"># Ensure output directory exists</span> </span></span><span class="line"><span class="cl"> <span class="n">os</span><span class="o">.</span><span class="n">makedirs</span><span class="p">(</span><span class="n">output_dir</span><span class="p">,</span> <span class="n">exist_ok</span><span class="o">=</span><span class="kc">True</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">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"># Restore full backup</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;Restoring full backup: </span><span class="si">{</span><span class="n">backup_path</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="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></span><span class="line"><span class="cl"> <span class="s2">&#34;&#34;&#34;CALL geode.restore.full($backup, $output, { </span></span></span><span class="line"><span class="cl"><span class="s2"> verify: true, </span></span></span><span class="line"><span class="cl"><span class="s2"> overwrite: true </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 class="p">{</span><span class="s2">&#34;backup&#34;</span><span class="p">:</span> <span class="n">backup_path</span><span class="p">,</span> <span class="s2">&#34;output&#34;</span><span class="p">:</span> <span class="n">output_dir</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">if</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">info</span> <span class="o">=</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></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; Nodes restored: </span><span class="si">{</span><span class="n">info</span><span class="p">[</span><span class="s1">&#39;node_count&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">as_int</span><span class="si">:</span><span class="s2">,</span><span class="si">}</span><span class="s2">&#34;</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; Relationships restored: </span><span class="si">{</span><span class="n">info</span><span class="p">[</span><span class="s1">&#39;relationship_count&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">as_int</span><span class="si">:</span><span class="s2">,</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"># Apply incremental backups</span> </span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">incremental_backups</span><span class="p">:</span> </span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">incr_backup</span> <span class="ow">in</span> <span class="n">incremental_backups</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;Applying incremental: </span><span class="si">{</span><span class="n">incr_backup</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="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></span><span class="line"><span class="cl"> <span class="s2">&#34;&#34;&#34;CALL geode.restore.incremental($backup, $output, { </span></span></span><span class="line"><span class="cl"><span class="s2"> verify: true </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 class="p">{</span><span class="s2">&#34;backup&#34;</span><span class="p">:</span> <span class="n">incr_backup</span><span class="p">,</span> <span class="s2">&#34;output&#34;</span><span class="p">:</span> <span class="n">output_dir</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">if</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">changes</span> <span class="o">=</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="s1">&#39;changes_applied&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">as_int</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; Changes applied: </span><span class="si">{</span><span class="n">changes</span><span class="si">:</span><span class="s2">,</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="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;</span><span class="se">\n</span><span class="s2">Restore complete. Data directory: </span><span class="si">{</span><span class="n">output_dir</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">async</span> <span class="k">def</span> <span class="nf">main</span><span class="p">():</span> </span></span><span class="line"><span class="cl"> <span class="k">await</span> <span class="n">restore_database</span><span class="p">(</span> </span></span><span class="line"><span class="cl"> <span class="n">backup_path</span><span class="o">=</span><span class="s2">&#34;/backups/full/geode-full-20260125.backup&#34;</span><span class="p">,</span> </span></span><span class="line"><span class="cl"> <span class="n">output_dir</span><span class="o">=</span><span class="s2">&#34;/var/lib/geode/data-restored&#34;</span><span class="p">,</span> </span></span><span class="line"><span class="cl"> <span class="n">incremental_backups</span><span class="o">=</span><span class="p">[</span> </span></span><span class="line"><span class="cl"> <span class="s2">&#34;/backups/incremental/geode-incr-20260126.backup&#34;</span><span class="p">,</span> </span></span><span class="line"><span class="cl"> <span class="s2">&#34;/backups/incremental/geode-incr-20260127.backup&#34;</span><span class="p">,</span> </span></span><span class="line"><span class="cl"> <span class="s2">&#34;/backups/incremental/geode-incr-20260128.backup&#34;</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><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="n">asyncio</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="n">main</span><span class="p">())</span> </span></span></code></pre></div> </div></div> </div> <h3 id="disaster-recovery-planning" class="position-relative d-flex align-items-center group"> <span>Disaster Recovery Planning</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="disaster-recovery-planning" aria-haspopup="dialog" aria-label="Share link: Disaster Recovery Planning"> <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="recovery-time-objective-rto-and-recovery-point-objective-rpo" class="position-relative d-flex align-items-center group"> <span>Recovery Time Objective (RTO) and Recovery Point Objective (RPO)</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="recovery-time-objective-rto-and-recovery-point-objective-rpo" aria-haspopup="dialog" aria-label="Share link: Recovery Time Objective (RTO) and Recovery Point Objective (RPO)"> <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><table> <thead> <tr> <th>Strategy</th> <th>RTO</th> <th>RPO</th> <th>Cost</th> </tr> </thead> <tbody> <tr> <td>Standby replica</td> <td>Minutes</td> <td>Seconds</td> <td>High</td> </tr> <tr> <td>Continuous backup</td> <td>Hours</td> <td>Minutes</td> <td>Medium</td> </tr> <tr> <td>Daily backup</td> <td>Hours-Days</td> <td>24 hours</td> <td>Low</td> </tr> </tbody> </table> <h4 id="disaster-recovery-runbook" class="position-relative d-flex align-items-center group"> <span>Disaster Recovery Runbook</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="disaster-recovery-runbook" aria-haspopup="dialog" aria-label="Share link: Disaster Recovery Runbook"> <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-markdown" data-lang="markdown"><span class="line"><span class="cl"><span class="gh"># Geode Disaster Recovery Runbook </span></span></span><span class="line"><span class="cl"><span class="gh"></span> </span></span><span class="line"><span class="cl"><span class="gu">## 1. Assess the Situation </span></span></span><span class="line"><span class="cl"><span class="gu"></span><span class="k">- [ ]</span> Identify the nature of the failure </span></span><span class="line"><span class="cl"><span class="k">- [ ]</span> Determine data loss extent </span></span><span class="line"><span class="cl"><span class="k">- [ ]</span> Notify stakeholders </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="gu">## 2. Activate Recovery </span></span></span><span class="line"><span class="cl"><span class="gu"></span><span class="k">- [ ]</span> Access backup storage </span></span><span class="line"><span class="cl"><span class="k">- [ ]</span> Identify latest valid backup </span></span><span class="line"><span class="cl"><span class="k">- [ ]</span> Prepare recovery environment </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="gu">## 3. Restore Database </span></span></span><span class="line"><span class="cl"><span class="gu"></span><span class="k">- [ ]</span> Deploy new Geode instance </span></span><span class="line"><span class="cl"><span class="k">- [ ]</span> Restore from backup </span></span><span class="line"><span class="cl"><span class="k">- [ ]</span> Apply incremental/WAL files </span></span><span class="line"><span class="cl"><span class="k">- [ ]</span> Verify data integrity </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="gu">## 4. Validate Recovery </span></span></span><span class="line"><span class="cl"><span class="gu"></span><span class="k">- [ ]</span> Run consistency checks </span></span><span class="line"><span class="cl"><span class="k">- [ ]</span> Execute test queries </span></span><span class="line"><span class="cl"><span class="k">- [ ]</span> Verify application connectivity </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="gu">## 5. Resume Operations </span></span></span><span class="line"><span class="cl"><span class="gu"></span><span class="k">- [ ]</span> Update DNS/load balancer </span></span><span class="line"><span class="cl"><span class="k">- [ ]</span> Monitor performance </span></span><span class="line"><span class="cl"><span class="k">- [ ]</span> Document incident </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="gu">## 6. Post-Incident </span></span></span><span class="line"><span class="cl"><span class="gu"></span><span class="k">- [ ]</span> Root cause analysis </span></span><span class="line"><span class="cl"><span class="k">- [ ]</span> Update procedures </span></span><span class="line"><span class="cl"><span class="k">- [ ]</span> Test improvements </span></span></code></pre></div> <h4 id="multi-region-backup-strategy" class="position-relative d-flex align-items-center group"> <span>Multi-Region Backup 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="multi-region-backup-strategy" aria-haspopup="dialog" aria-label="Share link: Multi-Region Backup 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><div class="docs-tabs mb-4"> <ul class="nav nav-tabs" id="tabs-1774880883859253796" role="tablist"><li class="nav-item" role="presentation"> <button class="nav-link active" id="tabs-1774880883859253796-tab-0-tab" data-bs-toggle="tab" data-bs-target="#tabs-1774880883859253796-tab-0" type="button" role="tab" aria-controls="tabs-1774880883859253796-tab-0" aria-selected="true" > Python </button> </li></ul> <div class="tab-content border border-top-0 rounded-bottom p-3" id="tabs-1774880883859253796-content"><div class="tab-pane fade show active" id="tabs-1774880883859253796-tab-0" role="tabpanel" aria-labelledby="tabs-1774880883859253796-tab-0-tab" > <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">asyncio</span> </span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">boto3</span> </span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">datetime</span> <span class="kn">import</span> <span class="n">datetime</span> </span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">geode_client</span> <span class="kn">import</span> <span class="n">Client</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">MultiRegionBackupManager</span><span class="p">:</span> </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">primary_region</span> <span class="o">=</span> <span class="s2">&#34;us-east-1&#34;</span> </span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">backup_regions</span> <span class="o">=</span> <span class="p">[</span><span class="s2">&#34;us-west-2&#34;</span><span class="p">,</span> <span class="s2">&#34;eu-west-1&#34;</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">s3_clients</span> <span class="o">=</span> <span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="n">region</span><span class="p">:</span> <span class="n">boto3</span><span class="o">.</span><span class="n">client</span><span class="p">(</span><span class="s1">&#39;s3&#39;</span><span class="p">,</span> <span class="n">region_name</span><span class="o">=</span><span class="n">region</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">region</span> <span class="ow">in</span> <span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">primary_region</span><span class="p">]</span> <span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">backup_regions</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">async</span> <span class="k">def</span> <span class="nf">create_and_replicate_backup</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;Create backup and replicate to multiple regions.&#34;&#34;&#34;</span> </span></span><span class="line"><span class="cl"> <span class="n">client</span> <span class="o">=</span> <span class="n">Client</span><span class="p">(</span><span class="n">host</span><span class="o">=</span><span class="s2">&#34;localhost&#34;</span><span class="p">,</span> <span class="n">port</span><span class="o">=</span><span class="mi">3141</span><span class="p">,</span> <span class="n">skip_verify</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="n">timestamp</span> <span class="o">=</span> <span class="n">datetime</span><span class="o">.</span><span class="n">now</span><span class="p">()</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="s2">&#34;%Y%m</span><span class="si">%d</span><span class="s2">-%H%M%S&#34;</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="n">local_path</span> <span class="o">=</span> <span class="sa">f</span><span class="s2">&#34;/tmp/geode-backup-</span><span class="si">{</span><span class="n">timestamp</span><span class="si">}</span><span class="s2">.backup&#34;</span> </span></span><span class="line"><span class="cl"> <span class="n">s3_key</span> <span class="o">=</span> <span class="sa">f</span><span class="s2">&#34;backups/geode/full-</span><span class="si">{</span><span class="n">timestamp</span><span class="si">}</span><span class="s2">.backup&#34;</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">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"># Create local backup</span> </span></span><span class="line"><span class="cl"> <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;Creating backup...&#34;</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></span><span class="line"><span class="cl"> <span class="s2">&#34;CALL geode.backup.full($path, {compression: &#39;gzip&#39;})&#34;</span><span class="p">,</span> </span></span><span class="line"><span class="cl"> <span class="p">{</span><span class="s2">&#34;path&#34;</span><span class="p">:</span> <span class="n">local_path</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="c1"># Upload to primary region</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;Uploading to </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">primary_region</span><span class="si">}</span><span class="s2">...&#34;</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">s3_clients</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">primary_region</span><span class="p">]</span><span class="o">.</span><span class="n">upload_file</span><span class="p">(</span> </span></span><span class="line"><span class="cl"> <span class="n">local_path</span><span class="p">,</span> </span></span><span class="line"><span class="cl"> <span class="sa">f</span><span class="s2">&#34;geode-backups-</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">primary_region</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">s3_key</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"># Replicate to backup regions</span> </span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">region</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">backup_regions</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;Replicating to </span><span class="si">{</span><span class="n">region</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"># Copy from primary to backup region</span> </span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">s3_clients</span><span class="p">[</span><span class="n">region</span><span class="p">]</span><span class="o">.</span><span class="n">copy_object</span><span class="p">(</span> </span></span><span class="line"><span class="cl"> <span class="n">CopySource</span><span class="o">=</span><span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="s1">&#39;Bucket&#39;</span><span class="p">:</span> <span class="sa">f</span><span class="s2">&#34;geode-backups-</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">primary_region</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">,</span> </span></span><span class="line"><span class="cl"> <span class="s1">&#39;Key&#39;</span><span class="p">:</span> <span class="n">s3_key</span> </span></span><span class="line"><span class="cl"> <span class="p">},</span> </span></span><span class="line"><span class="cl"> <span class="n">Bucket</span><span class="o">=</span><span class="sa">f</span><span class="s2">&#34;geode-backups-</span><span class="si">{</span><span class="n">region</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">Key</span><span class="o">=</span><span class="n">s3_key</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="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;Backup replicated to </span><span class="si">{</span><span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">backup_regions</span><span class="p">)</span><span class="si">}</span><span class="s2"> regions&#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"># Clean up local file</span> </span></span><span class="line"><span class="cl"> <span class="kn">import</span> <span class="nn">os</span> </span></span><span class="line"><span class="cl"> <span class="n">os</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">local_path</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">restore_from_nearest_region</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">target_dir</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;Restore from the nearest available region.&#34;&#34;&#34;</span> </span></span><span class="line"><span class="cl"> <span class="c1"># Check backup availability in each region</span> </span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">region</span> <span class="ow">in</span> <span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">primary_region</span><span class="p">]</span> <span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">backup_regions</span><span class="p">:</span> </span></span><span class="line"><span class="cl"> <span class="n">bucket</span> <span class="o">=</span> <span class="sa">f</span><span class="s2">&#34;geode-backups-</span><span class="si">{</span><span class="n">region</span><span class="si">}</span><span class="s2">&#34;</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">response</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">s3_clients</span><span class="p">[</span><span class="n">region</span><span class="p">]</span><span class="o">.</span><span class="n">list_objects_v2</span><span class="p">(</span> </span></span><span class="line"><span class="cl"> <span class="n">Bucket</span><span class="o">=</span><span class="n">bucket</span><span class="p">,</span> </span></span><span class="line"><span class="cl"> <span class="n">Prefix</span><span class="o">=</span><span class="s2">&#34;backups/geode/full-&#34;</span><span class="p">,</span> </span></span><span class="line"><span class="cl"> <span class="n">MaxKeys</span><span class="o">=</span><span class="mi">1</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">if</span> <span class="n">response</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">&#39;Contents&#39;</span><span class="p">):</span> </span></span><span class="line"><span class="cl"> <span class="n">latest</span> <span class="o">=</span> <span class="nb">sorted</span><span class="p">(</span> </span></span><span class="line"><span class="cl"> <span class="n">response</span><span class="p">[</span><span class="s1">&#39;Contents&#39;</span><span class="p">],</span> </span></span><span class="line"><span class="cl"> <span class="n">key</span><span class="o">=</span><span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="n">x</span><span class="p">[</span><span class="s1">&#39;LastModified&#39;</span><span class="p">],</span> </span></span><span class="line"><span class="cl"> <span class="n">reverse</span><span class="o">=</span><span class="kc">True</span> </span></span><span class="line"><span class="cl"> <span class="p">)[</span><span class="mi">0</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="sa">f</span><span class="s2">&#34;Restoring from </span><span class="si">{</span><span class="n">region</span><span class="si">}</span><span class="s2">: </span><span class="si">{</span><span class="n">latest</span><span class="p">[</span><span class="s1">&#39;Key&#39;</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></span><span class="line"><span class="cl"> <span class="c1"># Download backup</span> </span></span><span class="line"><span class="cl"> <span class="n">local_path</span> <span class="o">=</span> <span class="sa">f</span><span class="s2">&#34;/tmp/restore-</span><span class="si">{</span><span class="n">region</span><span class="si">}</span><span class="s2">.backup&#34;</span> </span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">s3_clients</span><span class="p">[</span><span class="n">region</span><span class="p">]</span><span class="o">.</span><span class="n">download_file</span><span class="p">(</span> </span></span><span class="line"><span class="cl"> <span class="n">bucket</span><span class="p">,</span> </span></span><span class="line"><span class="cl"> <span class="n">latest</span><span class="p">[</span><span class="s1">&#39;Key&#39;</span><span class="p">],</span> </span></span><span class="line"><span class="cl"> <span class="n">local_path</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"># Restore</span> </span></span><span class="line"><span class="cl"> <span class="n">client</span> <span class="o">=</span> <span class="n">Client</span><span class="p">(</span><span class="n">host</span><span class="o">=</span><span class="s2">&#34;localhost&#34;</span><span class="p">,</span> <span class="n">port</span><span class="o">=</span><span class="mi">3141</span><span class="p">,</span> <span class="n">skip_verify</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">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="k">await</span> <span class="n">conn</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span> </span></span><span class="line"><span class="cl"> <span class="s2">&#34;CALL geode.restore.full($path, $output)&#34;</span><span class="p">,</span> </span></span><span class="line"><span class="cl"> <span class="p">{</span><span class="s2">&#34;path&#34;</span><span class="p">:</span> <span class="n">local_path</span><span class="p">,</span> <span class="s2">&#34;output&#34;</span><span class="p">:</span> <span class="n">target_dir</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="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;Restore complete from </span><span class="si">{</span><span class="n">region</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">return</span> <span class="kc">True</span> </span></span><span class="line"><span class="cl"> </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="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;Region </span><span class="si">{</span><span class="n">region</span><span class="si">}</span><span class="s2"> unavailable: </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">continue</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="s2">&#34;No backup available in any region!&#34;</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="kc">False</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">main</span><span class="p">():</span> </span></span><span class="line"><span class="cl"> <span class="n">manager</span> <span class="o">=</span> <span class="n">MultiRegionBackupManager</span><span class="p">()</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="c1"># Create and replicate backup</span> </span></span><span class="line"><span class="cl"> <span class="k">await</span> <span class="n">manager</span><span class="o">.</span><span class="n">create_and_replicate_backup</span><span class="p">()</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="n">asyncio</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="n">main</span><span class="p">())</span> </span></span></code></pre></div> </div></div> </div> <h3 id="automated-backup-scheduling" class="position-relative d-flex align-items-center group"> <span>Automated Backup Scheduling</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-backup-scheduling" aria-haspopup="dialog" aria-label="Share link: Automated Backup Scheduling"> <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="cron-based-scheduling" class="position-relative d-flex align-items-center group"> <span>Cron-Based Scheduling</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="cron-based-scheduling" aria-haspopup="dialog" aria-label="Share link: Cron-Based Scheduling"> <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"># /etc/cron.d/geode-backup</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="c1"># Full backup every Sunday at 2 AM</span> </span></span><span class="line"><span class="cl"><span class="m">0</span> <span class="m">2</span> * * <span class="m">0</span> geode /usr/local/bin/geode-full-backup.sh &gt;&gt; /var/log/geode-backup.log 2&gt;<span class="p">&amp;</span><span class="m">1</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="c1"># Incremental backup every day at 2 AM (except Sunday)</span> </span></span><span class="line"><span class="cl"><span class="m">0</span> <span class="m">2</span> * * 1-6 geode /usr/local/bin/geode-incr-backup.sh &gt;&gt; /var/log/geode-backup.log 2&gt;<span class="p">&amp;</span><span class="m">1</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="c1"># WAL archiving check every 5 minutes</span> </span></span><span class="line"><span class="cl">*/5 * * * * geode /usr/local/bin/geode-wal-check.sh &gt;&gt; /var/log/geode-wal.log 2&gt;<span class="p">&amp;</span><span class="m">1</span> </span></span></code></pre></div> <h4 id="systemd-timer" class="position-relative d-flex align-items-center group"> <span>Systemd Timer</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="systemd-timer" aria-haspopup="dialog" aria-label="Share link: Systemd Timer"> <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-ini" data-lang="ini"><span class="line"><span class="cl"><span class="c1"># /etc/systemd/system/geode-backup.service</span> </span></span><span class="line"><span class="cl"><span class="k">[Unit]</span> </span></span><span class="line"><span class="cl"><span class="na">Description</span><span class="o">=</span><span class="s">Geode Database Backup</span> </span></span><span class="line"><span class="cl"><span class="na">After</span><span class="o">=</span><span class="s">geode.service</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="k">[Service]</span> </span></span><span class="line"><span class="cl"><span class="na">Type</span><span class="o">=</span><span class="s">oneshot</span> </span></span><span class="line"><span class="cl"><span class="na">User</span><span class="o">=</span><span class="s">geode</span> </span></span><span class="line"><span class="cl"><span class="na">ExecStart</span><span class="o">=</span><span class="s">/usr/local/bin/geode-backup.sh</span> </span></span><span class="line"><span class="cl"><span class="na">StandardOutput</span><span class="o">=</span><span class="s">journal</span> </span></span><span class="line"><span class="cl"><span class="na">StandardError</span><span class="o">=</span><span class="s">journal</span> </span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ini" data-lang="ini"><span class="line"><span class="cl"><span class="c1"># /etc/systemd/system/geode-backup.timer</span> </span></span><span class="line"><span class="cl"><span class="k">[Unit]</span> </span></span><span class="line"><span class="cl"><span class="na">Description</span><span class="o">=</span><span class="s">Daily Geode Backup Timer</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="k">[Timer]</span> </span></span><span class="line"><span class="cl"><span class="na">OnCalendar</span><span class="o">=</span><span class="s">*-*-* 02:00:00</span> </span></span><span class="line"><span class="cl"><span class="na">Persistent</span><span class="o">=</span><span class="s">true</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="k">[Install]</span> </span></span><span class="line"><span class="cl"><span class="na">WantedBy</span><span class="o">=</span><span class="s">timers.target</span> </span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># Enable timer</span> </span></span><span class="line"><span class="cl">systemctl <span class="nb">enable</span> geode-backup.timer </span></span><span class="line"><span class="cl">systemctl start geode-backup.timer </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="c1"># Check timer status</span> </span></span><span class="line"><span class="cl">systemctl list-timers <span class="p">|</span> grep geode </span></span></code></pre></div> <h4 id="comprehensive-backup-script" class="position-relative d-flex align-items-center group"> <span>Comprehensive Backup Script</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="comprehensive-backup-script" aria-haspopup="dialog" aria-label="Share link: Comprehensive Backup Script"> <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="cp">#!/bin/bash </span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="c1"># /usr/local/bin/geode-backup.sh</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="nb">set</span> -euo pipefail </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="c1"># Configuration</span> </span></span><span class="line"><span class="cl"><span class="nv">BACKUP_DIR</span><span class="o">=</span><span class="s2">&#34;/backups/geode&#34;</span> </span></span><span class="line"><span class="cl"><span class="nv">FULL_DIR</span><span class="o">=</span><span class="s2">&#34;</span><span class="si">${</span><span class="nv">BACKUP_DIR</span><span class="si">}</span><span class="s2">/full&#34;</span> </span></span><span class="line"><span class="cl"><span class="nv">INCR_DIR</span><span class="o">=</span><span class="s2">&#34;</span><span class="si">${</span><span class="nv">BACKUP_DIR</span><span class="si">}</span><span class="s2">/incremental&#34;</span> </span></span><span class="line"><span class="cl"><span class="nv">WAL_DIR</span><span class="o">=</span><span class="s2">&#34;</span><span class="si">${</span><span class="nv">BACKUP_DIR</span><span class="si">}</span><span class="s2">/wal&#34;</span> </span></span><span class="line"><span class="cl"><span class="nv">STATE_FILE</span><span class="o">=</span><span class="s2">&#34;</span><span class="si">${</span><span class="nv">BACKUP_DIR</span><span class="si">}</span><span class="s2">/backup_state.json&#34;</span> </span></span><span class="line"><span class="cl"><span class="nv">RETENTION_DAYS</span><span class="o">=</span><span class="m">30</span> </span></span><span class="line"><span class="cl"><span class="nv">FULL_BACKUP_DAY</span><span class="o">=</span><span class="m">0</span> <span class="c1"># Sunday</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="c1"># Logging</span> </span></span><span class="line"><span class="cl">log<span class="o">()</span> <span class="o">{</span> </span></span><span class="line"><span class="cl"> <span class="nb">echo</span> <span class="s2">&#34;[</span><span class="k">$(</span>date <span class="s1">&#39;+%Y-%m-%d %H:%M:%S&#39;</span><span class="k">)</span><span class="s2">] </span><span class="nv">$1</span><span class="s2">&#34;</span> </span></span><span class="line"><span class="cl"><span class="o">}</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="c1"># Create directories</span> </span></span><span class="line"><span class="cl">mkdir -p <span class="s2">&#34;</span><span class="si">${</span><span class="nv">FULL_DIR</span><span class="si">}</span><span class="s2">&#34;</span> <span class="s2">&#34;</span><span class="si">${</span><span class="nv">INCR_DIR</span><span class="si">}</span><span class="s2">&#34;</span> <span class="s2">&#34;</span><span class="si">${</span><span class="nv">WAL_DIR</span><span class="si">}</span><span class="s2">&#34;</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="c1"># Determine backup type</span> </span></span><span class="line"><span class="cl"><span class="nv">DAY_OF_WEEK</span><span class="o">=</span><span class="k">$(</span>date +%w<span class="k">)</span> </span></span><span class="line"><span class="cl"><span class="nv">TIMESTAMP</span><span class="o">=</span><span class="k">$(</span>date +%Y%m%d-%H%M%S<span class="k">)</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="o">[</span> <span class="s2">&#34;</span><span class="si">${</span><span class="nv">DAY_OF_WEEK</span><span class="si">}</span><span class="s2">&#34;</span> -eq <span class="s2">&#34;</span><span class="si">${</span><span class="nv">FULL_BACKUP_DAY</span><span class="si">}</span><span class="s2">&#34;</span> <span class="o">]</span><span class="p">;</span> <span class="k">then</span> </span></span><span class="line"><span class="cl"> <span class="nv">BACKUP_TYPE</span><span class="o">=</span><span class="s2">&#34;full&#34;</span> </span></span><span class="line"><span class="cl"> <span class="nv">BACKUP_FILE</span><span class="o">=</span><span class="s2">&#34;</span><span class="si">${</span><span class="nv">FULL_DIR</span><span class="si">}</span><span class="s2">/geode-full-</span><span class="si">${</span><span class="nv">TIMESTAMP</span><span class="si">}</span><span class="s2">.backup&#34;</span> </span></span><span class="line"><span class="cl"><span class="k">else</span> </span></span><span class="line"><span class="cl"> <span class="nv">BACKUP_TYPE</span><span class="o">=</span><span class="s2">&#34;incremental&#34;</span> </span></span><span class="line"><span class="cl"> <span class="nv">BACKUP_FILE</span><span class="o">=</span><span class="s2">&#34;</span><span class="si">${</span><span class="nv">INCR_DIR</span><span class="si">}</span><span class="s2">/geode-incr-</span><span class="si">${</span><span class="nv">TIMESTAMP</span><span class="si">}</span><span class="s2">.backup&#34;</span> </span></span><span class="line"><span class="cl"><span class="k">fi</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl">log <span class="s2">&#34;Starting </span><span class="si">${</span><span class="nv">BACKUP_TYPE</span><span class="si">}</span><span class="s2"> backup&#34;</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="c1"># Create backup</span> </span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="o">[</span> <span class="s2">&#34;</span><span class="si">${</span><span class="nv">BACKUP_TYPE</span><span class="si">}</span><span class="s2">&#34;</span> <span class="o">=</span> <span class="s2">&#34;full&#34;</span> <span class="o">]</span><span class="p">;</span> <span class="k">then</span> </span></span><span class="line"><span class="cl"> geode backup full <span class="se">\ </span></span></span><span class="line"><span class="cl"><span class="se"></span> --output <span class="s2">&#34;</span><span class="si">${</span><span class="nv">BACKUP_FILE</span><span class="si">}</span><span class="s2">&#34;</span> <span class="se">\ </span></span></span><span class="line"><span class="cl"><span class="se"></span> --compress gzip <span class="se">\ </span></span></span><span class="line"><span class="cl"><span class="se"></span> --verify </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="c1"># Update state with new full backup</span> </span></span><span class="line"><span class="cl"> <span class="nb">echo</span> <span class="s2">&#34;{\&#34;last_full\&#34;: \&#34;</span><span class="si">${</span><span class="nv">BACKUP_FILE</span><span class="si">}</span><span class="s2">\&#34;}&#34;</span> &gt; <span class="s2">&#34;</span><span class="si">${</span><span class="nv">STATE_FILE</span><span class="si">}</span><span class="s2">&#34;</span> </span></span><span class="line"><span class="cl"><span class="k">else</span> </span></span><span class="line"><span class="cl"> <span class="c1"># Read last full backup from state</span> </span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="o">[</span> -f <span class="s2">&#34;</span><span class="si">${</span><span class="nv">STATE_FILE</span><span class="si">}</span><span class="s2">&#34;</span> <span class="o">]</span><span class="p">;</span> <span class="k">then</span> </span></span><span class="line"><span class="cl"> <span class="nv">LAST_FULL</span><span class="o">=</span><span class="k">$(</span>jq -r <span class="s1">&#39;.last_full&#39;</span> <span class="s2">&#34;</span><span class="si">${</span><span class="nv">STATE_FILE</span><span class="si">}</span><span class="s2">&#34;</span><span class="k">)</span> </span></span><span class="line"><span class="cl"> <span class="k">else</span> </span></span><span class="line"><span class="cl"> log <span class="s2">&#34;No state file found. Creating full backup instead.&#34;</span> </span></span><span class="line"><span class="cl"> <span class="nv">BACKUP_FILE</span><span class="o">=</span><span class="s2">&#34;</span><span class="si">${</span><span class="nv">FULL_DIR</span><span class="si">}</span><span class="s2">/geode-full-</span><span class="si">${</span><span class="nv">TIMESTAMP</span><span class="si">}</span><span class="s2">.backup&#34;</span> </span></span><span class="line"><span class="cl"> geode backup full --output <span class="s2">&#34;</span><span class="si">${</span><span class="nv">BACKUP_FILE</span><span class="si">}</span><span class="s2">&#34;</span> --compress gzip --verify </span></span><span class="line"><span class="cl"> <span class="nb">echo</span> <span class="s2">&#34;{\&#34;last_full\&#34;: \&#34;</span><span class="si">${</span><span class="nv">BACKUP_FILE</span><span class="si">}</span><span class="s2">\&#34;}&#34;</span> &gt; <span class="s2">&#34;</span><span class="si">${</span><span class="nv">STATE_FILE</span><span class="si">}</span><span class="s2">&#34;</span> </span></span><span class="line"><span class="cl"> <span class="nb">exit</span> <span class="m">0</span> </span></span><span class="line"><span class="cl"> <span class="k">fi</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> geode backup incremental <span class="se">\ </span></span></span><span class="line"><span class="cl"><span class="se"></span> --base <span class="s2">&#34;</span><span class="si">${</span><span class="nv">LAST_FULL</span><span class="si">}</span><span class="s2">&#34;</span> <span class="se">\ </span></span></span><span class="line"><span class="cl"><span class="se"></span> --output <span class="s2">&#34;</span><span class="si">${</span><span class="nv">BACKUP_FILE</span><span class="si">}</span><span class="s2">&#34;</span> <span class="se">\ </span></span></span><span class="line"><span class="cl"><span class="se"></span> --compress gzip <span class="se">\ </span></span></span><span class="line"><span class="cl"><span class="se"></span> --verify </span></span><span class="line"><span class="cl"><span class="k">fi</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="c1"># Verify backup</span> </span></span><span class="line"><span class="cl">log <span class="s2">&#34;Verifying backup...&#34;</span> </span></span><span class="line"><span class="cl">geode backup verify <span class="s2">&#34;</span><span class="si">${</span><span class="nv">BACKUP_FILE</span><span class="si">}</span><span class="s2">&#34;</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="c1"># Get backup size</span> </span></span><span class="line"><span class="cl"><span class="nv">SIZE</span><span class="o">=</span><span class="k">$(</span>du -h <span class="s2">&#34;</span><span class="si">${</span><span class="nv">BACKUP_FILE</span><span class="si">}</span><span class="s2">&#34;</span> <span class="p">|</span> cut -f1<span class="k">)</span> </span></span><span class="line"><span class="cl">log <span class="s2">&#34;Backup complete: </span><span class="si">${</span><span class="nv">BACKUP_FILE</span><span class="si">}</span><span class="s2"> (</span><span class="si">${</span><span class="nv">SIZE</span><span class="si">}</span><span class="s2">)&#34;</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="c1"># Clean up old backups</span> </span></span><span class="line"><span class="cl">log <span class="s2">&#34;Cleaning up backups older than </span><span class="si">${</span><span class="nv">RETENTION_DAYS</span><span class="si">}</span><span class="s2"> days...&#34;</span> </span></span><span class="line"><span class="cl">find <span class="s2">&#34;</span><span class="si">${</span><span class="nv">FULL_DIR</span><span class="si">}</span><span class="s2">&#34;</span> -name <span class="s2">&#34;*.backup&#34;</span> -mtime +<span class="si">${</span><span class="nv">RETENTION_DAYS</span><span class="si">}</span> -delete </span></span><span class="line"><span class="cl">find <span class="s2">&#34;</span><span class="si">${</span><span class="nv">INCR_DIR</span><span class="si">}</span><span class="s2">&#34;</span> -name <span class="s2">&#34;*.backup&#34;</span> -mtime +<span class="si">${</span><span class="nv">RETENTION_DAYS</span><span class="si">}</span> -delete </span></span><span class="line"><span class="cl">find <span class="s2">&#34;</span><span class="si">${</span><span class="nv">WAL_DIR</span><span class="si">}</span><span class="s2">&#34;</span> -name <span class="s2">&#34;*.wal&#34;</span> -mtime +<span class="si">${</span><span class="nv">RETENTION_DAYS</span><span class="si">}</span> -delete </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="c1"># Upload to remote storage (optional)</span> </span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="o">[</span> -n <span class="s2">&#34;</span><span class="si">${</span><span class="nv">S3_BUCKET</span><span class="k">:-</span><span class="si">}</span><span class="s2">&#34;</span> <span class="o">]</span><span class="p">;</span> <span class="k">then</span> </span></span><span class="line"><span class="cl"> log <span class="s2">&#34;Uploading to S3...&#34;</span> </span></span><span class="line"><span class="cl"> aws s3 cp <span class="s2">&#34;</span><span class="si">${</span><span class="nv">BACKUP_FILE</span><span class="si">}</span><span class="s2">&#34;</span> <span class="s2">&#34;s3://</span><span class="si">${</span><span class="nv">S3_BUCKET</span><span class="si">}</span><span class="s2">/backups/geode/&#34;</span> </span></span><span class="line"><span class="cl"><span class="k">fi</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl">log <span class="s2">&#34;Backup job completed successfully&#34;</span> </span></span></code></pre></div> <h3 id="monitoring-backups" class="position-relative d-flex align-items-center group"> <span>Monitoring Backups</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="monitoring-backups" aria-haspopup="dialog" aria-label="Share link: Monitoring Backups"> <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="backup-health-checks" class="position-relative d-flex align-items-center group"> <span>Backup Health Checks</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="backup-health-checks" aria-haspopup="dialog" aria-label="Share link: Backup Health Checks"> <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">asyncio</span> </span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">os</span> </span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">datetime</span> <span class="kn">import</span> <span class="n">datetime</span><span class="p">,</span> <span class="n">timedelta</span> </span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">geode_client</span> <span class="kn">import</span> <span class="n">Client</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">check_backup_health</span><span class="p">(</span><span class="n">backup_dir</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;Check backup health and alert on issues.&#34;&#34;&#34;</span> </span></span><span class="line"><span class="cl"> <span class="n">issues</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"># Check for recent full backup</span> </span></span><span class="line"><span class="cl"> <span class="n">full_dir</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">backup_dir</span><span class="p">,</span> <span class="s2">&#34;full&#34;</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">exists</span><span class="p">(</span><span class="n">full_dir</span><span class="p">):</span> </span></span><span class="line"><span class="cl"> <span class="n">full_backups</span> <span class="o">=</span> <span class="nb">sorted</span><span class="p">([</span> </span></span><span class="line"><span class="cl"> <span class="n">f</span> <span class="k">for</span> <span class="n">f</span> <span class="ow">in</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">full_dir</span><span class="p">)</span> <span class="k">if</span> <span class="n">f</span><span class="o">.</span><span class="n">endswith</span><span class="p">(</span><span class="s1">&#39;.backup&#39;</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="p">],</span> <span class="n">reverse</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="ow">not</span> <span class="n">full_backups</span><span class="p">:</span> </span></span><span class="line"><span class="cl"> <span class="n">issues</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s2">&#34;No full backups found&#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="n">latest_full</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">full_dir</span><span class="p">,</span> <span class="n">full_backups</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> </span></span><span class="line"><span class="cl"> <span class="n">mtime</span> <span class="o">=</span> <span class="n">datetime</span><span class="o">.</span><span class="n">fromtimestamp</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">getmtime</span><span class="p">(</span><span class="n">latest_full</span><span class="p">))</span> </span></span><span class="line"><span class="cl"> <span class="n">age_days</span> <span class="o">=</span> <span class="p">(</span><span class="n">datetime</span><span class="o">.</span><span class="n">now</span><span class="p">()</span> <span class="o">-</span> <span class="n">mtime</span><span class="p">)</span><span class="o">.</span><span class="n">days</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">age_days</span> <span class="o">&gt;</span> <span class="mi">7</span><span class="p">:</span> </span></span><span class="line"><span class="cl"> <span class="n">issues</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;Latest full backup is </span><span class="si">{</span><span class="n">age_days</span><span class="si">}</span><span class="s2"> days old&#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"># Check for recent incremental backup</span> </span></span><span class="line"><span class="cl"> <span class="n">incr_dir</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">backup_dir</span><span class="p">,</span> <span class="s2">&#34;incremental&#34;</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">exists</span><span class="p">(</span><span class="n">incr_dir</span><span class="p">):</span> </span></span><span class="line"><span class="cl"> <span class="n">incr_backups</span> <span class="o">=</span> <span class="nb">sorted</span><span class="p">([</span> </span></span><span class="line"><span class="cl"> <span class="n">f</span> <span class="k">for</span> <span class="n">f</span> <span class="ow">in</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">incr_dir</span><span class="p">)</span> <span class="k">if</span> <span class="n">f</span><span class="o">.</span><span class="n">endswith</span><span class="p">(</span><span class="s1">&#39;.backup&#39;</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="p">],</span> <span class="n">reverse</span><span class="o">=</span><span class="kc">True</span><span class="p">)</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">incr_backups</span><span class="p">:</span> </span></span><span class="line"><span class="cl"> <span class="n">latest_incr</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">incr_dir</span><span class="p">,</span> <span class="n">incr_backups</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> </span></span><span class="line"><span class="cl"> <span class="n">mtime</span> <span class="o">=</span> <span class="n">datetime</span><span class="o">.</span><span class="n">fromtimestamp</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">getmtime</span><span class="p">(</span><span class="n">latest_incr</span><span class="p">))</span> </span></span><span class="line"><span class="cl"> <span class="n">age_hours</span> <span class="o">=</span> <span class="p">(</span><span class="n">datetime</span><span class="o">.</span><span class="n">now</span><span class="p">()</span> <span class="o">-</span> <span class="n">mtime</span><span class="p">)</span><span class="o">.</span><span class="n">total_seconds</span><span class="p">()</span> <span class="o">/</span> <span class="mi">3600</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">age_hours</span> <span class="o">&gt;</span> <span class="mi">25</span><span class="p">:</span> <span class="c1"># More than 25 hours</span> </span></span><span class="line"><span class="cl"> <span class="n">issues</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;Latest incremental is </span><span class="si">{</span><span class="n">age_hours</span><span class="si">:</span><span class="s2">.0f</span><span class="si">}</span><span class="s2"> hours old&#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"># Check WAL archiving</span> </span></span><span class="line"><span class="cl"> <span class="n">wal_dir</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">backup_dir</span><span class="p">,</span> <span class="s2">&#34;wal&#34;</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">exists</span><span class="p">(</span><span class="n">wal_dir</span><span class="p">):</span> </span></span><span class="line"><span class="cl"> <span class="n">wal_files</span> <span class="o">=</span> <span class="p">[</span><span class="n">f</span> <span class="k">for</span> <span class="n">f</span> <span class="ow">in</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">wal_dir</span><span class="p">)</span> <span class="k">if</span> <span class="n">f</span><span class="o">.</span><span class="n">endswith</span><span class="p">(</span><span class="s1">&#39;.wal&#39;</span><span class="p">)]</span> </span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">wal_files</span><span class="p">:</span> </span></span><span class="line"><span class="cl"> <span class="n">latest_wal</span> <span class="o">=</span> <span class="nb">max</span><span class="p">(</span><span class="n">wal_files</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="k">lambda</span> <span class="n">f</span><span class="p">:</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">getmtime</span><span class="p">(</span> </span></span><span class="line"><span class="cl"> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">wal_dir</span><span class="p">,</span> <span class="n">f</span><span class="p">)))</span> </span></span><span class="line"><span class="cl"> <span class="n">mtime</span> <span class="o">=</span> <span class="n">datetime</span><span class="o">.</span><span class="n">fromtimestamp</span><span class="p">(</span> </span></span><span class="line"><span class="cl"> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">getmtime</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">wal_dir</span><span class="p">,</span> <span class="n">latest_wal</span><span class="p">)))</span> </span></span><span class="line"><span class="cl"> <span class="n">age_minutes</span> <span class="o">=</span> <span class="p">(</span><span class="n">datetime</span><span class="o">.</span><span class="n">now</span><span class="p">()</span> <span class="o">-</span> <span class="n">mtime</span><span class="p">)</span><span class="o">.</span><span class="n">total_seconds</span><span class="p">()</span> <span class="o">/</span> <span class="mi">60</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">age_minutes</span> <span class="o">&gt;</span> <span class="mi">10</span><span class="p">:</span> </span></span><span class="line"><span class="cl"> <span class="n">issues</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;WAL archiving may be delayed (</span><span class="si">{</span><span class="n">age_minutes</span><span class="si">:</span><span class="s2">.0f</span><span class="si">}</span><span class="s2"> min)&#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"># Check disk space</span> </span></span><span class="line"><span class="cl"> <span class="n">statvfs</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">statvfs</span><span class="p">(</span><span class="n">backup_dir</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="n">free_gb</span> <span class="o">=</span> <span class="p">(</span><span class="n">statvfs</span><span class="o">.</span><span class="n">f_frsize</span> <span class="o">*</span> <span class="n">statvfs</span><span class="o">.</span><span class="n">f_bavail</span><span class="p">)</span> <span class="o">/</span> <span class="p">(</span><span class="mi">1024</span><span class="o">**</span><span class="mi">3</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">free_gb</span> <span class="o">&lt;</span> <span class="mi">50</span><span class="p">:</span> </span></span><span class="line"><span class="cl"> <span class="n">issues</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;Low disk space: </span><span class="si">{</span><span class="n">free_gb</span><span class="si">:</span><span class="s2">.1f</span><span class="si">}</span><span class="s2"> GB free&#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"># Report</span> </span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">issues</span><span class="p">:</span> </span></span><span class="line"><span class="cl"> <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;BACKUP HEALTH CHECK: ISSUES FOUND&#34;</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">issue</span> <span class="ow">in</span> <span class="n">issues</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">issue</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">return</span> <span class="kc">False</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="nb">print</span><span class="p">(</span><span class="s2">&#34;BACKUP HEALTH CHECK: OK&#34;</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="kc">True</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="n">asyncio</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="n">check_backup_health</span><span class="p">(</span><span class="s2">&#34;/backups/geode&#34;</span><span class="p">))</span> </span></span></code></pre></div> <h4 id="prometheus-metrics" class="position-relative d-flex align-items-center group"> <span>Prometheus Metrics</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="prometheus-metrics" aria-haspopup="dialog" aria-label="Share link: Prometheus Metrics"> <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="c1"># Expose backup metrics for Prometheus</span> </span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">prometheus_client</span> <span class="kn">import</span> <span class="n">Gauge</span><span class="p">,</span> <span class="n">Counter</span><span class="p">,</span> <span class="n">start_http_server</span> </span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">os</span> </span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">datetime</span> <span class="kn">import</span> <span class="n">datetime</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="c1"># Define metrics</span> </span></span><span class="line"><span class="cl"><span class="n">backup_age_seconds</span> <span class="o">=</span> <span class="n">Gauge</span><span class="p">(</span> </span></span><span class="line"><span class="cl"> <span class="s1">&#39;geode_backup_age_seconds&#39;</span><span class="p">,</span> </span></span><span class="line"><span class="cl"> <span class="s1">&#39;Age of the latest backup in seconds&#39;</span><span class="p">,</span> </span></span><span class="line"><span class="cl"> <span class="p">[</span><span class="s1">&#39;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">backup_size_bytes</span> <span class="o">=</span> <span class="n">Gauge</span><span class="p">(</span> </span></span><span class="line"><span class="cl"> <span class="s1">&#39;geode_backup_size_bytes&#39;</span><span class="p">,</span> </span></span><span class="line"><span class="cl"> <span class="s1">&#39;Size of the latest backup in bytes&#39;</span><span class="p">,</span> </span></span><span class="line"><span class="cl"> <span class="p">[</span><span class="s1">&#39;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">backup_count</span> <span class="o">=</span> <span class="n">Gauge</span><span class="p">(</span> </span></span><span class="line"><span class="cl"> <span class="s1">&#39;geode_backup_count&#39;</span><span class="p">,</span> </span></span><span class="line"><span class="cl"> <span class="s1">&#39;Number of backup files&#39;</span><span class="p">,</span> </span></span><span class="line"><span class="cl"> <span class="p">[</span><span class="s1">&#39;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">backup_disk_free_bytes</span> <span class="o">=</span> <span class="n">Gauge</span><span class="p">(</span> </span></span><span class="line"><span class="cl"> <span class="s1">&#39;geode_backup_disk_free_bytes&#39;</span><span class="p">,</span> </span></span><span class="line"><span class="cl"> <span class="s1">&#39;Free disk space for backups&#39;</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">update_metrics</span><span class="p">(</span><span class="n">backup_dir</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;Update Prometheus metrics.&#34;&#34;&#34;</span> </span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">backup_type</span> <span class="ow">in</span> <span class="p">[</span><span class="s1">&#39;full&#39;</span><span class="p">,</span> <span class="s1">&#39;incremental&#39;</span><span class="p">]:</span> </span></span><span class="line"><span class="cl"> <span class="n">type_dir</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">backup_dir</span><span class="p">,</span> <span class="n">backup_type</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="ow">not</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">exists</span><span class="p">(</span><span class="n">type_dir</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></span><span class="line"><span class="cl"> <span class="n">backups</span> <span class="o">=</span> <span class="p">[</span><span class="n">f</span> <span class="k">for</span> <span class="n">f</span> <span class="ow">in</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">type_dir</span><span class="p">)</span> <span class="k">if</span> <span class="n">f</span><span class="o">.</span><span class="n">endswith</span><span class="p">(</span><span class="s1">&#39;.backup&#39;</span><span class="p">)]</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="c1"># Count</span> </span></span><span class="line"><span class="cl"> <span class="n">backup_count</span><span class="o">.</span><span class="n">labels</span><span class="p">(</span><span class="nb">type</span><span class="o">=</span><span class="n">backup_type</span><span class="p">)</span><span class="o">.</span><span class="n">set</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">backups</span><span class="p">))</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">backups</span><span class="p">:</span> </span></span><span class="line"><span class="cl"> <span class="c1"># Latest backup</span> </span></span><span class="line"><span class="cl"> <span class="n">latest</span> <span class="o">=</span> <span class="nb">max</span><span class="p">(</span><span class="n">backups</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="k">lambda</span> <span class="n">f</span><span class="p">:</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">getmtime</span><span class="p">(</span> </span></span><span class="line"><span class="cl"> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">type_dir</span><span class="p">,</span> <span class="n">f</span><span class="p">)))</span> </span></span><span class="line"><span class="cl"> <span class="n">latest_path</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">type_dir</span><span class="p">,</span> <span class="n">latest</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="c1"># Age</span> </span></span><span class="line"><span class="cl"> <span class="n">age</span> <span class="o">=</span> <span class="n">datetime</span><span class="o">.</span><span class="n">now</span><span class="p">()</span><span class="o">.</span><span class="n">timestamp</span><span class="p">()</span> <span class="o">-</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">getmtime</span><span class="p">(</span><span class="n">latest_path</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="n">backup_age_seconds</span><span class="o">.</span><span class="n">labels</span><span class="p">(</span><span class="nb">type</span><span class="o">=</span><span class="n">backup_type</span><span class="p">)</span><span class="o">.</span><span class="n">set</span><span class="p">(</span><span class="n">age</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="c1"># Size</span> </span></span><span class="line"><span class="cl"> <span class="n">size</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">getsize</span><span class="p">(</span><span class="n">latest_path</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="n">backup_size_bytes</span><span class="o">.</span><span class="n">labels</span><span class="p">(</span><span class="nb">type</span><span class="o">=</span><span class="n">backup_type</span><span class="p">)</span><span class="o">.</span><span class="n">set</span><span class="p">(</span><span class="n">size</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="c1"># Disk space</span> </span></span><span class="line"><span class="cl"> <span class="n">statvfs</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">statvfs</span><span class="p">(</span><span class="n">backup_dir</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="n">free_bytes</span> <span class="o">=</span> <span class="n">statvfs</span><span class="o">.</span><span class="n">f_frsize</span> <span class="o">*</span> <span class="n">statvfs</span><span class="o">.</span><span class="n">f_bavail</span> </span></span><span class="line"><span class="cl"> <span class="n">backup_disk_free_bytes</span><span class="o">.</span><span class="n">set</span><span class="p">(</span><span class="n">free_bytes</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="c1"># Start metrics server</span> </span></span><span class="line"><span class="cl"><span class="n">start_http_server</span><span class="p">(</span><span class="mi">9090</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="c1"># Update metrics periodically</span> </span></span><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="k">while</span> <span class="kc">True</span><span class="p">:</span> </span></span><span class="line"><span class="cl"> <span class="n">update_metrics</span><span class="p">(</span><span class="s2">&#34;/backups/geode&#34;</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="n">time</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="mi">60</span><span class="p">)</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="backup-checklist" class="position-relative d-flex align-items-center group"> <span>Backup Checklist</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="backup-checklist" aria-haspopup="dialog" aria-label="Share link: Backup Checklist"> <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><ul> <li><input disabled="" type="checkbox"> <strong>Regular full backups</strong> (weekly recommended)</li> <li><input disabled="" type="checkbox"> <strong>Daily incremental backups</strong></li> <li><input disabled="" type="checkbox"> <strong>WAL archiving enabled</strong> for point-in-time recovery</li> <li><input disabled="" type="checkbox"> <strong>Backup verification</strong> after each backup</li> <li><input disabled="" type="checkbox"> <strong>Test restores</strong> at least monthly</li> <li><input disabled="" type="checkbox"> <strong>Off-site backup storage</strong> (different region/provider)</li> <li><input disabled="" type="checkbox"> <strong>Encryption</strong> for backups containing sensitive data</li> <li><input disabled="" type="checkbox"> <strong>Monitoring and alerting</strong> for backup failures</li> <li><input disabled="" type="checkbox"> <strong>Documented recovery procedures</strong></li> <li><input disabled="" type="checkbox"> <strong>Regular DR drills</strong></li> </ul> <h4 id="security-considerations" class="position-relative d-flex align-items-center group"> <span>Security Considerations</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="security-considerations" aria-haspopup="dialog" aria-label="Share link: Security Considerations"> <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"># Encrypt backup</span> </span></span><span class="line"><span class="cl">geode backup create <span class="se">\ </span></span></span><span class="line"><span class="cl"><span class="se"></span> --output /backups/geode.backup <span class="se">\ </span></span></span><span class="line"><span class="cl"><span class="se"></span> --encrypt <span class="se">\ </span></span></span><span class="line"><span class="cl"><span class="se"></span> --encryption-key-file /etc/geode/backup.key </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="c1"># Restore encrypted backup</span> </span></span><span class="line"><span class="cl">geode restore <span class="se">\ </span></span></span><span class="line"><span class="cl"><span class="se"></span> --backup /backups/geode.backup <span class="se">\ </span></span></span><span class="line"><span class="cl"><span class="se"></span> --decrypt <span class="se">\ </span></span></span><span class="line"><span class="cl"><span class="se"></span> --encryption-key-file /etc/geode/backup.key <span class="se">\ </span></span></span><span class="line"><span class="cl"><span class="se"></span> --output /var/lib/geode/data </span></span></code></pre></div> <h3 id="next-steps" class="position-relative d-flex align-items-center group"> <span>Next Steps</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="next-steps" aria-haspopup="dialog" aria-label="Share link: Next Steps"> <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="/guides/data-import/" >Data Import Guide</a> - Import data into Geode</li> <li><a href="/guides/data-export/" >Data Export Guide</a> - Export your data</li> <li><a href="/guides/high-availability/" >High Availability Guide</a> - Configure HA</li> <li><a href="/docs/performance/" >Performance Guide</a> - Optimize performance</li> </ul> <h3 id="resources" class="position-relative d-flex align-items-center group"> <span>Resources</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="resources" aria-haspopup="dialog" aria-label="Share link: Resources"> <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/reference/cli-and-api/" >CLI Reference</a> </li> <li><a href="/docs/configuration/" >Configuration Reference</a> </li> <li><a href="/docs/api-reference/" >API Reference</a> </li> <li><a href="https://forum.geodedb.com" aria-label="Community Forum – opens in new window" target="_blank" rel="noopener noreferrer" >Community Forum <span aria-hidden="true" class="external-icon">↗</span> </a> </li> </ul> <hr> <p><strong>Questions?</strong> Discuss backup strategies in our <a href="https://forum.geodedb.com" aria-label="forum – opens in new window" target="_blank" rel="noopener noreferrer" >forum <span aria-hidden="true" class="external-icon">↗</span> </a> .</p>