mirror of
https://github.com/clockworklabs/SpacetimeDB.git
synced 2026-05-14 19:58:24 -04:00
348 lines
80 KiB
HTML
348 lines
80 KiB
HTML
<!doctype html>
|
||
<html lang="en" dir="ltr" class="docs-wrapper plugin-docs plugin-id-default docs-version-current docs-doc-page docs-doc-id-Subscriptions/Subscription-Reference" data-has-hydrated="false">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="generator" content="Docusaurus v3.9.1">
|
||
<title data-rh="true">Subscription Reference | SpacetimeDB docs</title><meta data-rh="true" name="viewport" content="width=device-width,initial-scale=1"><meta data-rh="true" name="twitter:card" content="summary_large_image"><meta data-rh="true" property="og:url" content="https://docs.spacetimedb.com/subscriptions"><meta data-rh="true" property="og:locale" content="en"><meta data-rh="true" name="docusaurus_locale" content="en"><meta data-rh="true" name="docsearch:language" content="en"><meta data-rh="true" name="docusaurus_version" content="current"><meta data-rh="true" name="docusaurus_tag" content="docs-default-current"><meta data-rh="true" name="docsearch:version" content="current"><meta data-rh="true" name="docsearch:docusaurus_tag" content="docs-default-current"><meta data-rh="true" property="og:title" content="Subscription Reference | SpacetimeDB docs"><meta data-rh="true" name="description" content="The subscription API allows a client to replicate a subset of a database."><meta data-rh="true" property="og:description" content="The subscription API allows a client to replicate a subset of a database."><link data-rh="true" rel="icon" href="/images/favicon.ico"><link data-rh="true" rel="canonical" href="https://docs.spacetimedb.com/subscriptions"><link data-rh="true" rel="alternate" href="https://docs.spacetimedb.com/subscriptions" hreflang="en"><link data-rh="true" rel="alternate" href="https://docs.spacetimedb.com/subscriptions" hreflang="x-default"><link data-rh="true" rel="preconnect" href="https://QBC7Z9KXS2-dsn.algolia.net" crossorigin="anonymous"><script data-rh="true" type="application/ld+json">{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Subscription Reference","item":"https://docs.spacetimedb.com/subscriptions"}]}</script><link rel="search" type="application/opensearchdescription+xml" title="SpacetimeDB docs" href="/opensearch.xml"><link rel="stylesheet" href="/assets/css/styles.0cb9f7a7.css">
|
||
<script src="/assets/js/runtime~main.d71df0f5.js" defer="defer"></script>
|
||
<script src="/assets/js/main.31d95d83.js" defer="defer"></script>
|
||
</head>
|
||
<body class="navigation-with-keyboard">
|
||
<svg style="display: none;"><defs>
|
||
<symbol id="theme-svg-external-link" viewBox="0 0 24 24"><path fill="currentColor" d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"/></symbol>
|
||
</defs></svg>
|
||
<script>document.documentElement.setAttribute("data-theme","light"),document.documentElement.setAttribute("data-theme-choice","light"),function(){try{const c=new URLSearchParams(window.location.search).entries();for(var[t,e]of c)if(t.startsWith("docusaurus-data-")){var a=t.replace("docusaurus-data-","data-");document.documentElement.setAttribute(a,e)}}catch(t){}}()</script><div id="__docusaurus"><link rel="preload" as="image" href="https://spacetimedb.com/images/brand.png"><div role="region" aria-label="Skip to main content"><a class="skipToContent_6jFv" href="#__docusaurus_skipToContent_fallback">Skip to main content</a></div><nav aria-label="Main" class="theme-layout-navbar navbar navbar--fixed-top"><div class="navbar__inner"><div class="theme-layout-navbar-left navbar__items"><button aria-label="Toggle navigation bar" aria-expanded="false" class="navbar__toggle clean-btn" type="button"><svg width="30" height="30" viewBox="0 0 30 30" aria-hidden="true"><path stroke="currentColor" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" d="M4 7h22M4 15h22M4 23h22"></path></svg></button><a class="navbar__brand" href="/"><div class="navbar__logo"><img src="https://spacetimedb.com/images/brand.png" alt="SpacetimeDB Logo" class="themedComponent_rvet themedComponent--light_mbAJ"><img src="https://spacetimedb.com/images/brand.png" alt="SpacetimeDB Logo" class="themedComponent_rvet themedComponent--dark_Ncy6"></div></a><div class="navbarSearchContainer_AesG"><button type="button" class="DocSearch DocSearch-Button" aria-label="Search (Command+K)"><span class="DocSearch-Button-Container"><svg width="20" height="20" class="DocSearch-Search-Icon" viewBox="0 0 20 20" aria-hidden="true"><path d="M14.386 14.386l4.0877 4.0877-4.0877-4.0877c-2.9418 2.9419-7.7115 2.9419-10.6533 0-2.9419-2.9418-2.9419-7.7115 0-10.6533 2.9418-2.9419 7.7115-2.9419 10.6533 0 2.9419 2.9418 2.9419 7.7115 0 10.6533z" stroke="currentColor" fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round"></path></svg><span class="DocSearch-Button-Placeholder">Search</span></span><span class="DocSearch-Button-Keys"></span></button></div></div><div class="theme-layout-navbar-right navbar__items navbar__items--right"><a href="https://spacetimedb.com/install" target="_blank" rel="noopener noreferrer" class="navbar__item navbar__link">Install</a><a href="https://spacetimedb.com/pricing" target="_blank" rel="noopener noreferrer" class="navbar__item navbar__link">Pricing</a><a href="https://spacetimedb.com/maincloud" target="_blank" rel="noopener noreferrer" class="navbar__item navbar__link">Maincloud</a><a href="https://spacetimedb.com/blog" target="_blank" rel="noopener noreferrer" class="navbar__item navbar__link">Blog</a><a href="https://spacetimedb.com/community" target="_blank" rel="noopener noreferrer" class="navbar__item navbar__link">Community</a></div></div><div role="presentation" class="navbar-sidebar__backdrop"></div></nav><div id="__docusaurus_skipToContent_fallback" class="theme-layout-main main-wrapper mainWrapper_hV_y"><div class="docsWrapper_f07g"><button aria-label="Scroll back to top" class="clean-btn theme-back-to-top-button backToTopButton_MJiz" type="button"></button><div class="docRoot_Gd2s"><aside class="theme-doc-sidebar-container docSidebarContainer_fSpF"><div class="sidebarViewport_YElg"><div class="sidebar_kjg4"><nav aria-label="Docs sidebar" class="menu thin-scrollbar menu_AG0n"><ul class="theme-doc-sidebar-menu menu__list"><li class="theme-doc-sidebar-item-category theme-doc-sidebar-item-category-level-1 menu__list-item menu__list-item--collapsed"><div class="menu__list-item-collapsible"><a class="categoryLink_ggI5 menu__link menu__link--sublist menu__link--sublist-caret" role="button" aria-expanded="false" href="/"><span title="Intro" class="categoryLinkLabel_EDYQ">Intro</span></a></div></li><li class="theme-doc-sidebar-item-category theme-doc-sidebar-item-category-level-1 menu__list-item menu__list-item--collapsed"><div class="menu__list-item-collapsible"><a class="categoryLink_ggI5 menu__link menu__link--sublist menu__link--sublist-caret" role="button" aria-expanded="false" href="/deploying/maincloud"><span title="Deploying" class="categoryLinkLabel_EDYQ">Deploying</span></a></div></li><li class="theme-doc-sidebar-item-category theme-doc-sidebar-item-category-level-1 menu__list-item menu__list-item--collapsed"><div class="menu__list-item-collapsible"><a class="categoryLink_ggI5 menu__link menu__link--sublist menu__link--sublist-caret" role="button" aria-expanded="false" href="/unity"><span title="Unity tutorial" class="categoryLinkLabel_EDYQ">Unity tutorial</span></a></div></li><li class="theme-doc-sidebar-item-category theme-doc-sidebar-item-category-level-1 menu__list-item menu__list-item--collapsed"><div class="menu__list-item-collapsible"><a class="categoryLink_ggI5 menu__link menu__link--sublist menu__link--sublist-caret" role="button" aria-expanded="false" href="/unreal"><span title="Unreal Tutorial" class="categoryLinkLabel_EDYQ">Unreal Tutorial</span></a></div></li><li class="theme-doc-sidebar-item-category theme-doc-sidebar-item-category-level-1 menu__list-item menu__list-item--collapsed"><div class="menu__list-item-collapsible"><a class="categoryLink_ggI5 menu__link menu__link--sublist menu__link--sublist-caret" role="button" aria-expanded="false" href="/cli-reference"><span title="CLI Reference" class="categoryLinkLabel_EDYQ">CLI Reference</span></a></div></li><li class="theme-doc-sidebar-item-category theme-doc-sidebar-item-category-level-1 menu__list-item menu__list-item--collapsed"><div class="menu__list-item-collapsible"><a class="categoryLink_ggI5 menu__link menu__link--sublist menu__link--sublist-caret" role="button" aria-expanded="false" href="/modules"><span title="Server Module Languages" class="categoryLinkLabel_EDYQ">Server Module Languages</span></a></div></li><li class="theme-doc-sidebar-item-category theme-doc-sidebar-item-category-level-1 menu__list-item menu__list-item--collapsed"><div class="menu__list-item-collapsible"><a class="categoryLink_ggI5 menu__link menu__link--sublist menu__link--sublist-caret" role="button" aria-expanded="false" href="/sdks"><span title="Client SDK Languages" class="categoryLinkLabel_EDYQ">Client SDK Languages</span></a></div></li><li class="theme-doc-sidebar-item-category theme-doc-sidebar-item-category-level-1 menu__list-item menu__list-item--collapsed"><div class="menu__list-item-collapsible"><a class="categoryLink_ggI5 menu__link menu__link--sublist menu__link--sublist-caret" role="button" aria-expanded="false" href="/sql"><span title="SQL" class="categoryLinkLabel_EDYQ">SQL</span></a></div></li><li class="theme-doc-sidebar-item-category theme-doc-sidebar-item-category-level-1 menu__list-item"><div class="menu__list-item-collapsible"><a class="categoryLink_ggI5 menu__link menu__link--sublist menu__link--sublist-caret menu__link--active" role="button" aria-expanded="true" href="/subscriptions"><span title="Subscriptions" class="categoryLinkLabel_EDYQ">Subscriptions</span></a></div><ul class="menu__list"><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class="menu__link menu__link--active" aria-current="page" tabindex="0" href="/subscriptions"><span title="Subscription Reference" class="linkLabel_dpMB">Subscription Reference</span></a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class="menu__link" tabindex="0" href="/subscriptions/semantics"><span title="Subscription Semantics" class="linkLabel_dpMB">Subscription Semantics</span></a></li></ul></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-1 menu__list-item"><a class="menu__link" href="/rls"><span title="Row Level Security" class="linkLabel_dpMB">Row Level Security</span></a></li><li class="theme-doc-sidebar-item-category theme-doc-sidebar-item-category-level-1 menu__list-item menu__list-item--collapsed"><div class="menu__list-item-collapsible"><a class="categoryLink_ggI5 menu__link menu__link--sublist menu__link--sublist-caret" role="button" aria-expanded="false" href="/how-to/incremental-migrations"><span title="How-To" class="categoryLinkLabel_EDYQ">How-To</span></a></div></li><li class="theme-doc-sidebar-item-category theme-doc-sidebar-item-category-level-1 menu__list-item menu__list-item--collapsed"><div class="menu__list-item-collapsible"><a class="categoryLink_ggI5 menu__link menu__link--sublist menu__link--sublist-caret" role="button" aria-expanded="false" href="/spacetimeauth"><span title="SpacetimeAuth" class="categoryLinkLabel_EDYQ">SpacetimeAuth</span></a></div></li><li class="theme-doc-sidebar-item-category theme-doc-sidebar-item-category-level-1 menu__list-item menu__list-item--collapsed"><div class="menu__list-item-collapsible"><a class="categoryLink_ggI5 menu__link menu__link--sublist menu__link--sublist-caret" role="button" aria-expanded="false" href="/http/authorization"><span title="HTTP API" class="categoryLinkLabel_EDYQ">HTTP API</span></a></div></li><li class="theme-doc-sidebar-item-category theme-doc-sidebar-item-category-level-1 menu__list-item menu__list-item--collapsed"><div class="menu__list-item-collapsible"><a class="categoryLink_ggI5 menu__link menu__link--sublist menu__link--sublist-caret" role="button" aria-expanded="false" href="/webassembly-abi"><span title="Internals" class="categoryLinkLabel_EDYQ">Internals</span></a></div></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-1 menu__list-item"><a class="menu__link" href="/appendix"><span title="Appendix" class="linkLabel_dpMB">Appendix</span></a></li></ul></nav></div></div></aside><main class="docMainContainer_dkUT"><div class="container padding-top--md padding-bottom--lg"><div class="row"><div class="col docItemCol_w2oE"><div class="docItemContainer_f71m"><article><nav class="theme-doc-breadcrumbs breadcrumbsContainer_xsLZ" aria-label="Breadcrumbs"><ul class="breadcrumbs"><li class="breadcrumbs__item"><a aria-label="Home page" class="breadcrumbs__link" href="/"><svg viewBox="0 0 24 24" class="breadcrumbHomeIcon_oyay"><path d="M10 19v-5h4v5c0 .55.45 1 1 1h3c.55 0 1-.45 1-1v-7h1.7c.46 0 .68-.57.33-.87L12.67 3.6c-.38-.34-.96-.34-1.34 0l-8.36 7.53c-.34.3-.13.87.33.87H5v7c0 .55.45 1 1 1h3c.55 0 1-.45 1-1z" fill="currentColor"></path></svg></a></li><li class="breadcrumbs__item"><span class="breadcrumbs__link">Subscriptions</span></li><li class="breadcrumbs__item breadcrumbs__item--active"><span class="breadcrumbs__link">Subscription Reference</span></li></ul></nav><div class="tocCollapsible_dqme theme-doc-toc-mobile tocMobile_Z34P"><button type="button" class="clean-btn tocCollapsibleButton_QMSE">On this page</button></div><div class="theme-doc-markdown markdown"><header><h1>The SpacetimeDB Subscription API</h1></header>
|
||
<p>The subscription API allows a client to replicate a subset of a database.
|
||
It does so by registering SQL queries, which we call subscriptions, through a database connection.
|
||
A client will only receive updates for rows that match the subscriptions it has registered.</p>
|
||
<p>For more information on syntax and requirements see the <a href="/sql#subscriptions">SQL docs</a>.</p>
|
||
<p>This guide describes the two main interfaces that comprise the API - <code>SubscriptionBuilder</code> and <code>SubscriptionHandle</code>.
|
||
By using these interfaces, you can create efficient and responsive client applications that only receive the data they need.</p>
|
||
<h2 class="anchor anchorWithStickyNavbar_wKCU" id="subscriptionbuilder">SubscriptionBuilder<a href="#subscriptionbuilder" class="hash-link" aria-label="Direct link to SubscriptionBuilder" title="Direct link to SubscriptionBuilder" translate="no"></a></h2>
|
||
<div class="theme-tabs-container tabs-container tabList_MbSD"><ul role="tablist" aria-orientation="horizontal" class="tabs"><li role="tab" tabindex="0" aria-selected="true" class="tabs__item tabItem_Ssy3 tabs__item--active">Rust</li><li role="tab" tabindex="-1" aria-selected="false" class="tabs__item tabItem_Ssy3">C#</li></ul><div class="margin-top--md"><div role="tabpanel" class="tabItem_sydm"><pre tabindex="0" class="codeBlockStandalone_pMzE thin-scrollbar codeBlockContainer_HZVP theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><code class="codeBlockLines_ckKi"><span class="line"><span style="color:#FF79C6">pub</span><span style="color:#FF79C6"> struct</span><span style="color:#8BE9FD;font-style:italic"> SubscriptionBuilder</span><span style="color:#F8F8F2"><</span><span style="color:#8BE9FD;font-style:italic">M</span><span style="color:#FF79C6">:</span><span style="color:#8BE9FD;font-style:italic"> SpacetimeModule</span><span style="color:#F8F8F2">> { </span><span style="color:#6272A4">/* private fields */</span><span style="color:#F8F8F2"> }</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#FF79C6">impl</span><span style="color:#F8F8F2"><</span><span style="color:#8BE9FD;font-style:italic">M</span><span style="color:#FF79C6">:</span><span style="color:#8BE9FD;font-style:italic"> SpacetimeModule</span><span style="color:#F8F8F2">> </span><span style="color:#8BE9FD;font-style:italic">SubscriptionBuilder</span><span style="color:#F8F8F2"><</span><span style="color:#8BE9FD;font-style:italic">M</span><span style="color:#F8F8F2">> {</span></span>
|
||
<span class="line"><span style="color:#6272A4"> /// Register a callback that runs when the subscription has been applied.</span></span>
|
||
<span class="line"><span style="color:#6272A4"> /// This callback receives a context containing the current state of the subscription.</span></span>
|
||
<span class="line"><span style="color:#FF79C6"> pub</span><span style="color:#FF79C6"> fn</span><span style="color:#50FA7B"> on_applied</span><span style="color:#F8F8F2">(</span><span style="color:#FF79C6">mut</span><span style="color:#BD93F9;font-style:italic"> self</span><span style="color:#F8F8F2">, callback</span><span style="color:#FF79C6">:</span><span style="color:#FF79C6"> impl</span><span style="color:#50FA7B"> FnOnce</span><span style="color:#F8F8F2">(</span><span style="color:#FF79C6">&</span><span style="color:#F8F8F2">M</span><span style="color:#FF79C6">::</span><span style="color:#8BE9FD;font-style:italic">SubscriptionEventContext</span><span style="color:#F8F8F2">) </span><span style="color:#FF79C6">+</span><span style="color:#8BE9FD;font-style:italic"> Send</span><span style="color:#FF79C6"> +</span><span style="color:#F8F8F2"> '</span><span style="color:#8BE9FD;font-style:italic">static</span><span style="color:#F8F8F2">);</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#6272A4"> /// Register a callback to run when the subscription fails.</span></span>
|
||
<span class="line"><span style="color:#6272A4"> ///</span></span>
|
||
<span class="line"><span style="color:#6272A4"> /// Note that this callback may run either when attempting to apply the subscription,</span></span>
|
||
<span class="line"><span style="color:#6272A4"> /// in which case [`Self::on_applied`] will never run,</span></span>
|
||
<span class="line"><span style="color:#6272A4"> /// or later during the subscription's lifetime if the module's interface changes,</span></span>
|
||
<span class="line"><span style="color:#6272A4"> /// in which case [`Self::on_applied`] may have already run.</span></span>
|
||
<span class="line"><span style="color:#FF79C6"> pub</span><span style="color:#FF79C6"> fn</span><span style="color:#50FA7B"> on_error</span><span style="color:#F8F8F2">(</span><span style="color:#FF79C6">mut</span><span style="color:#BD93F9;font-style:italic"> self</span><span style="color:#F8F8F2">, callback</span><span style="color:#FF79C6">:</span><span style="color:#FF79C6"> impl</span><span style="color:#50FA7B"> FnOnce</span><span style="color:#F8F8F2">(</span><span style="color:#FF79C6">&</span><span style="color:#F8F8F2">M</span><span style="color:#FF79C6">::</span><span style="color:#8BE9FD;font-style:italic">ErrorContext</span><span style="color:#F8F8F2">, </span><span style="color:#FF79C6">crate::</span><span style="color:#8BE9FD;font-style:italic">Error</span><span style="color:#F8F8F2">) </span><span style="color:#FF79C6">+</span><span style="color:#8BE9FD;font-style:italic"> Send</span><span style="color:#FF79C6"> +</span><span style="color:#F8F8F2"> '</span><span style="color:#8BE9FD;font-style:italic">static</span><span style="color:#F8F8F2">);</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#6272A4"> /// Subscribe to a subset of the database via a set of SQL queries.</span></span>
|
||
<span class="line"><span style="color:#6272A4"> /// Returns a handle which you can use to monitor or drop the subscription later.</span></span>
|
||
<span class="line"><span style="color:#FF79C6"> pub</span><span style="color:#FF79C6"> fn</span><span style="color:#50FA7B"> subscribe</span><span style="color:#F8F8F2"><</span><span style="color:#8BE9FD;font-style:italic">Queries</span><span style="color:#FF79C6">:</span><span style="color:#8BE9FD;font-style:italic"> IntoQueries</span><span style="color:#F8F8F2">>(</span><span style="color:#BD93F9;font-style:italic">self</span><span style="color:#F8F8F2">, query_sql</span><span style="color:#FF79C6">:</span><span style="color:#8BE9FD;font-style:italic"> Queries</span><span style="color:#F8F8F2">) </span><span style="color:#FF79C6">-></span><span style="color:#F8F8F2"> M</span><span style="color:#FF79C6">::</span><span style="color:#8BE9FD;font-style:italic">SubscriptionHandle</span><span style="color:#F8F8F2">;</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#6272A4"> /// Subscribe to all rows from all tables.</span></span>
|
||
<span class="line"><span style="color:#6272A4"> ///</span></span>
|
||
<span class="line"><span style="color:#6272A4"> /// This method is intended as a convenience</span></span>
|
||
<span class="line"><span style="color:#6272A4"> /// for applications where client-side memory use and network bandwidth are not concerns.</span></span>
|
||
<span class="line"><span style="color:#6272A4"> /// Applications where these resources are a constraint</span></span>
|
||
<span class="line"><span style="color:#6272A4"> /// should register more precise queries via [`Self::subscribe`]</span></span>
|
||
<span class="line"><span style="color:#6272A4"> /// in order to replicate only the subset of data which the client needs to function.</span></span>
|
||
<span class="line"><span style="color:#FF79C6"> pub</span><span style="color:#FF79C6"> fn</span><span style="color:#50FA7B"> subscribe_to_all_tables</span><span style="color:#F8F8F2">(</span><span style="color:#BD93F9;font-style:italic">self</span><span style="color:#F8F8F2">);</span></span>
|
||
<span class="line"><span style="color:#F8F8F2">}</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#6272A4">/// Types which specify a list of query strings.</span></span>
|
||
<span class="line"><span style="color:#FF79C6">pub</span><span style="color:#FF79C6"> trait</span><span style="color:#8BE9FD;font-style:italic"> IntoQueries</span><span style="color:#F8F8F2"> {</span></span>
|
||
<span class="line"><span style="color:#FF79C6"> fn</span><span style="color:#50FA7B"> into_queries</span><span style="color:#F8F8F2">(</span><span style="color:#BD93F9;font-style:italic">self</span><span style="color:#F8F8F2">) </span><span style="color:#FF79C6">-></span><span style="color:#8BE9FD;font-style:italic"> Box</span><span style="color:#F8F8F2"><[</span><span style="color:#8BE9FD;font-style:italic">Box</span><span style="color:#F8F8F2"><</span><span style="color:#8BE9FD;font-style:italic">str</span><span style="color:#F8F8F2">>]>;</span></span>
|
||
<span class="line"><span style="color:#F8F8F2">}</span></span></code></pre></div><div role="tabpanel" class="tabItem_sydm" hidden=""><pre tabindex="0" class="codeBlockStandalone_pMzE thin-scrollbar codeBlockContainer_HZVP theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><code class="codeBlockLines_ckKi"><span class="line"><span style="color:#FF79C6">public</span><span style="color:#FF79C6"> sealed</span><span style="color:#FF79C6"> class</span><span style="color:#8BE9FD"> SubscriptionBuilder</span></span>
|
||
<span class="line"><span style="color:#F8F8F2">{</span></span>
|
||
<span class="line"><span style="color:#6272A4"> /// </span><span style="color:#F8F8F2"><</span><span style="color:#FF79C6">summary</span><span style="color:#F8F8F2">></span></span>
|
||
<span class="line"><span style="color:#6272A4"> /// Register a callback to run when the subscription is applied.</span></span>
|
||
<span class="line"><span style="color:#6272A4"> /// </span><span style="color:#F8F8F2"></</span><span style="color:#FF79C6">summary</span><span style="color:#F8F8F2">></span></span>
|
||
<span class="line"><span style="color:#FF79C6"> public</span><span style="color:#8BE9FD;font-style:italic"> SubscriptionBuilder</span><span style="color:#50FA7B"> OnApplied</span><span style="color:#F8F8F2">(</span></span>
|
||
<span class="line"><span style="color:#8BE9FD;font-style:italic"> Action</span><span style="color:#F8F8F2"><</span><span style="color:#8BE9FD;font-style:italic">SubscriptionEventContext</span><span style="color:#F8F8F2">> </span><span style="color:#FFB86C;font-style:italic">callback</span></span>
|
||
<span class="line"><span style="color:#F8F8F2"> );</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#6272A4"> /// </span><span style="color:#F8F8F2"><</span><span style="color:#FF79C6">summary</span><span style="color:#F8F8F2">></span></span>
|
||
<span class="line"><span style="color:#6272A4"> /// Register a callback to run when the subscription fails.</span></span>
|
||
<span class="line"><span style="color:#6272A4"> ///</span></span>
|
||
<span class="line"><span style="color:#6272A4"> /// Note that this callback may run either when attempting to apply the subscription,</span></span>
|
||
<span class="line"><span style="color:#6272A4"> /// in which case </span><span style="color:#F8F8F2"><</span><span style="color:#FF79C6">c</span><span style="color:#F8F8F2">></span><span style="color:#6272A4">Self::on_applied</span><span style="color:#F8F8F2"></</span><span style="color:#FF79C6">c</span><span style="color:#F8F8F2">></span><span style="color:#6272A4"> will never run,</span></span>
|
||
<span class="line"><span style="color:#6272A4"> /// or later during the subscription's lifetime if the module's interface changes,</span></span>
|
||
<span class="line"><span style="color:#6272A4"> /// in which case </span><span style="color:#F8F8F2"><</span><span style="color:#FF79C6">c</span><span style="color:#F8F8F2">></span><span style="color:#6272A4">Self::on_applied</span><span style="color:#F8F8F2"></</span><span style="color:#FF79C6">c</span><span style="color:#F8F8F2">></span><span style="color:#6272A4"> may have already run.</span></span>
|
||
<span class="line"><span style="color:#6272A4"> /// </span><span style="color:#F8F8F2"></</span><span style="color:#FF79C6">summary</span><span style="color:#F8F8F2">></span></span>
|
||
<span class="line"><span style="color:#FF79C6"> public</span><span style="color:#8BE9FD;font-style:italic"> SubscriptionBuilder</span><span style="color:#50FA7B"> OnError</span><span style="color:#F8F8F2">(</span></span>
|
||
<span class="line"><span style="color:#8BE9FD;font-style:italic"> Action</span><span style="color:#F8F8F2"><</span><span style="color:#8BE9FD;font-style:italic">ErrorContext</span><span style="color:#F8F8F2">, </span><span style="color:#8BE9FD;font-style:italic">Exception</span><span style="color:#F8F8F2">> </span><span style="color:#FFB86C;font-style:italic">callback</span></span>
|
||
<span class="line"><span style="color:#F8F8F2"> );</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#6272A4"> /// </span><span style="color:#F8F8F2"><</span><span style="color:#FF79C6">summary</span><span style="color:#F8F8F2">></span></span>
|
||
<span class="line"><span style="color:#6272A4"> /// Subscribe to the following SQL queries.</span></span>
|
||
<span class="line"><span style="color:#6272A4"> ///</span></span>
|
||
<span class="line"><span style="color:#6272A4"> /// This method returns immediately, with the data not yet added to the DbConnection.</span></span>
|
||
<span class="line"><span style="color:#6272A4"> /// The provided callbacks will be invoked once the data is returned from the remote server.</span></span>
|
||
<span class="line"><span style="color:#6272A4"> /// Data from all the provided queries will be returned at the same time.</span></span>
|
||
<span class="line"><span style="color:#6272A4"> ///</span></span>
|
||
<span class="line"><span style="color:#6272A4"> /// See the SpacetimeDB SQL docs for more information on SQL syntax:</span></span>
|
||
<span class="line"><span style="color:#6272A4"> /// </span><span style="color:#F8F8F2"><</span><span style="color:#FF79C6">a</span><span style="color:#50FA7B;font-style:italic"> href</span><span style="color:#6272A4">=</span><span style="color:#E9F284">"</span><span style="color:#F1FA8C">https://spacetimedb.com/docs/sql</span><span style="color:#E9F284">"</span><span style="color:#F8F8F2">></span><span style="color:#6272A4">https://spacetimedb.com/docs/sql</span><span style="color:#F8F8F2"></</span><span style="color:#FF79C6">a</span><span style="color:#F8F8F2">></span></span>
|
||
<span class="line"><span style="color:#6272A4"> /// </span><span style="color:#F8F8F2"></</span><span style="color:#FF79C6">summary</span><span style="color:#F8F8F2">></span></span>
|
||
<span class="line"><span style="color:#FF79C6"> public</span><span style="color:#8BE9FD;font-style:italic"> SubscriptionHandle</span><span style="color:#50FA7B"> Subscribe</span><span style="color:#F8F8F2">(</span></span>
|
||
<span class="line"><span style="color:#FF79C6"> string</span><span style="color:#F8F8F2">[] </span><span style="color:#FFB86C;font-style:italic">querySqls</span></span>
|
||
<span class="line"><span style="color:#F8F8F2"> );</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#6272A4"> /// </span><span style="color:#F8F8F2"><</span><span style="color:#FF79C6">summary</span><span style="color:#F8F8F2">></span></span>
|
||
<span class="line"><span style="color:#6272A4"> /// Subscribe to all rows from all tables.</span></span>
|
||
<span class="line"><span style="color:#6272A4"> ///</span></span>
|
||
<span class="line"><span style="color:#6272A4"> /// This method is intended as a convenience</span></span>
|
||
<span class="line"><span style="color:#6272A4"> /// for applications where client-side memory use and network bandwidth are not concerns.</span></span>
|
||
<span class="line"><span style="color:#6272A4"> /// Applications where these resources are a constraint</span></span>
|
||
<span class="line"><span style="color:#6272A4"> /// should register more precise queries via </span><span style="color:#F8F8F2"><</span><span style="color:#FF79C6">c</span><span style="color:#F8F8F2">></span><span style="color:#6272A4">Self.Subscribe</span><span style="color:#F8F8F2"></</span><span style="color:#FF79C6">c</span><span style="color:#F8F8F2">></span></span>
|
||
<span class="line"><span style="color:#6272A4"> /// in order to replicate only the subset of data which the client needs to function.</span></span>
|
||
<span class="line"><span style="color:#6272A4"> /// </span><span style="color:#F8F8F2"></</span><span style="color:#FF79C6">summary</span><span style="color:#F8F8F2">></span></span>
|
||
<span class="line"><span style="color:#FF79C6"> public</span><span style="color:#FF79C6"> void</span><span style="color:#50FA7B"> SubscribeToAllTables</span><span style="color:#F8F8F2">();</span></span>
|
||
<span class="line"><span style="color:#F8F8F2">}</span></span></code></pre></div></div></div>
|
||
<p>A <code>SubscriptionBuilder</code> provides an interface for registering subscription queries with a database.
|
||
It allows you to register callbacks that run when the subscription is successfully applied or when an error occurs.
|
||
Once applied, a client will start receiving row updates to its client cache.
|
||
A client can react to these updates by registering row callbacks for the appropriate table.</p>
|
||
<h3 class="anchor anchorWithStickyNavbar_wKCU" id="example-usage">Example Usage<a href="#example-usage" class="hash-link" aria-label="Direct link to Example Usage" title="Direct link to Example Usage" translate="no"></a></h3>
|
||
<div class="theme-tabs-container tabs-container tabList_MbSD"><ul role="tablist" aria-orientation="horizontal" class="tabs"><li role="tab" tabindex="0" aria-selected="true" class="tabs__item tabItem_Ssy3 tabs__item--active">Rust</li><li role="tab" tabindex="-1" aria-selected="false" class="tabs__item tabItem_Ssy3">C#</li></ul><div class="margin-top--md"><div role="tabpanel" class="tabItem_sydm"><pre tabindex="0" class="codeBlockStandalone_pMzE thin-scrollbar codeBlockContainer_HZVP theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><code class="codeBlockLines_ckKi"><span class="line"><span style="color:#6272A4">// Establish a database connection</span></span>
|
||
<span class="line"><span style="color:#FF79C6">let</span><span style="color:#F8F8F2"> conn</span><span style="color:#FF79C6">:</span><span style="color:#8BE9FD;font-style:italic"> DbConnection</span><span style="color:#FF79C6"> =</span><span style="color:#50FA7B"> connect_to_db</span><span style="color:#F8F8F2">();</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#6272A4">// Register a subscription with the database</span></span>
|
||
<span class="line"><span style="color:#FF79C6">let</span><span style="color:#F8F8F2"> subscription_handle </span><span style="color:#FF79C6">=</span><span style="color:#F8F8F2"> conn</span></span>
|
||
<span class="line"><span style="color:#FF79C6"> .</span><span style="color:#50FA7B">subscription_builder</span><span style="color:#F8F8F2">()</span></span>
|
||
<span class="line"><span style="color:#FF79C6"> .</span><span style="color:#50FA7B">on_applied</span><span style="color:#F8F8F2">(</span><span style="color:#FF79C6">|</span><span style="color:#F8F8F2">ctx</span><span style="color:#FF79C6">|</span><span style="color:#F8F8F2"> { </span><span style="color:#6272A4">/* handle applied state */</span><span style="color:#F8F8F2"> })</span></span>
|
||
<span class="line"><span style="color:#FF79C6"> .</span><span style="color:#50FA7B">on_error</span><span style="color:#F8F8F2">(</span><span style="color:#FF79C6">|</span><span style="color:#F8F8F2">error_ctx, error</span><span style="color:#FF79C6">|</span><span style="color:#F8F8F2"> { </span><span style="color:#6272A4">/* handle error */</span><span style="color:#F8F8F2"> })</span></span>
|
||
<span class="line"><span style="color:#FF79C6"> .</span><span style="color:#50FA7B">subscribe</span><span style="color:#F8F8F2">([</span><span style="color:#F1FA8C">"SELECT * FROM user"</span><span style="color:#F8F8F2">, </span><span style="color:#F1FA8C">"SELECT * FROM message"</span><span style="color:#F8F8F2">]);</span></span></code></pre></div><div role="tabpanel" class="tabItem_sydm" hidden=""><pre tabindex="0" class="codeBlockStandalone_pMzE thin-scrollbar codeBlockContainer_HZVP theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><code class="codeBlockLines_ckKi"><span class="line"><span style="color:#6272A4">// Establish a database connection</span></span>
|
||
<span class="line"><span style="color:#FF79C6">var</span><span style="color:#F8F8F2"> conn </span><span style="color:#FF79C6">=</span><span style="color:#50FA7B"> ConnectToDB</span><span style="color:#F8F8F2">();</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#6272A4">// Register a subscription with the database</span></span>
|
||
<span class="line"><span style="color:#FF79C6">var</span><span style="color:#F8F8F2"> userSubscription </span><span style="color:#FF79C6">=</span><span style="color:#F8F8F2"> conn</span></span>
|
||
<span class="line"><span style="color:#F8F8F2"> .</span><span style="color:#50FA7B">SubscriptionBuilder</span><span style="color:#F8F8F2">()</span></span>
|
||
<span class="line"><span style="color:#F8F8F2"> .</span><span style="color:#50FA7B">OnApplied</span><span style="color:#F8F8F2">((</span><span style="color:#FFB86C;font-style:italic">ctx</span><span style="color:#F8F8F2">) </span><span style="color:#FF79C6">=></span><span style="color:#F8F8F2"> { </span><span style="color:#6272A4">/* handle applied state */</span><span style="color:#F8F8F2"> })</span></span>
|
||
<span class="line"><span style="color:#F8F8F2"> .</span><span style="color:#50FA7B">OnError</span><span style="color:#F8F8F2">((</span><span style="color:#FFB86C;font-style:italic">errorCtx</span><span style="color:#F8F8F2">, </span><span style="color:#FFB86C;font-style:italic">error</span><span style="color:#F8F8F2">) </span><span style="color:#FF79C6">=></span><span style="color:#F8F8F2"> { </span><span style="color:#6272A4">/* handle error */</span><span style="color:#F8F8F2"> })</span></span>
|
||
<span class="line"><span style="color:#F8F8F2"> .</span><span style="color:#50FA7B">Subscribe</span><span style="color:#F8F8F2">(</span><span style="color:#FF79C6">new</span><span style="color:#FF79C6"> string</span><span style="color:#F8F8F2">[] { </span><span style="color:#E9F284">"</span><span style="color:#F1FA8C">SELECT * FROM user</span><span style="color:#E9F284">"</span><span style="color:#F8F8F2">, </span><span style="color:#E9F284">"</span><span style="color:#F1FA8C">SELECT * FROM message</span><span style="color:#E9F284">"</span><span style="color:#F8F8F2"> });</span></span></code></pre></div></div></div>
|
||
<h2 class="anchor anchorWithStickyNavbar_wKCU" id="subscriptionhandle">SubscriptionHandle<a href="#subscriptionhandle" class="hash-link" aria-label="Direct link to SubscriptionHandle" title="Direct link to SubscriptionHandle" translate="no"></a></h2>
|
||
<div class="theme-tabs-container tabs-container tabList_MbSD"><ul role="tablist" aria-orientation="horizontal" class="tabs"><li role="tab" tabindex="0" aria-selected="true" class="tabs__item tabItem_Ssy3 tabs__item--active">Rust</li><li role="tab" tabindex="-1" aria-selected="false" class="tabs__item tabItem_Ssy3">C#</li></ul><div class="margin-top--md"><div role="tabpanel" class="tabItem_sydm"><pre tabindex="0" class="codeBlockStandalone_pMzE thin-scrollbar codeBlockContainer_HZVP theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><code class="codeBlockLines_ckKi"><span class="line"><span style="color:#FF79C6">pub</span><span style="color:#FF79C6"> trait</span><span style="color:#8BE9FD;font-style:italic"> SubscriptionHandle</span><span style="color:#FF79C6">:</span><span style="color:#8BE9FD;font-style:italic"> InModule</span><span style="color:#FF79C6"> +</span><span style="color:#8BE9FD;font-style:italic"> Clone</span><span style="color:#FF79C6"> +</span><span style="color:#8BE9FD;font-style:italic"> Send</span><span style="color:#FF79C6"> +</span><span style="color:#F8F8F2"> '</span><span style="color:#8BE9FD;font-style:italic">static</span></span>
|
||
<span class="line"><span style="color:#FF79C6">where</span></span>
|
||
<span class="line"><span style="color:#BD93F9;font-style:italic"> Self</span><span style="color:#FF79C6">::</span><span style="color:#8BE9FD;font-style:italic">Module</span><span style="color:#FF79C6">:</span><span style="color:#8BE9FD;font-style:italic"> SpacetimeModule</span><span style="color:#F8F8F2"><</span><span style="color:#8BE9FD;font-style:italic">SubscriptionHandle</span><span style="color:#FF79C6"> =</span><span style="color:#BD93F9;font-style:italic"> Self</span><span style="color:#F8F8F2">>,</span></span>
|
||
<span class="line"><span style="color:#F8F8F2">{</span></span>
|
||
<span class="line"><span style="color:#6272A4"> /// Returns `true` if the subscription has been ended.</span></span>
|
||
<span class="line"><span style="color:#6272A4"> /// That is, if it has been unsubscribed or terminated due to an error.</span></span>
|
||
<span class="line"><span style="color:#FF79C6"> fn</span><span style="color:#50FA7B"> is_ended</span><span style="color:#F8F8F2">(</span><span style="color:#FF79C6">&</span><span style="color:#BD93F9;font-style:italic">self</span><span style="color:#F8F8F2">) </span><span style="color:#FF79C6">-></span><span style="color:#8BE9FD;font-style:italic"> bool</span><span style="color:#F8F8F2">;</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#6272A4"> /// Returns `true` if the subscription is currently active.</span></span>
|
||
<span class="line"><span style="color:#FF79C6"> fn</span><span style="color:#50FA7B"> is_active</span><span style="color:#F8F8F2">(</span><span style="color:#FF79C6">&</span><span style="color:#BD93F9;font-style:italic">self</span><span style="color:#F8F8F2">) </span><span style="color:#FF79C6">-></span><span style="color:#8BE9FD;font-style:italic"> bool</span><span style="color:#F8F8F2">;</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#6272A4"> /// Unsubscribe from the query controlled by this `SubscriptionHandle`,</span></span>
|
||
<span class="line"><span style="color:#6272A4"> /// then run `on_end` when its rows are removed from the client cache.</span></span>
|
||
<span class="line"><span style="color:#6272A4"> /// Returns an error if the subscription is already ended,</span></span>
|
||
<span class="line"><span style="color:#6272A4"> /// or if unsubscribe has already been called.</span></span>
|
||
<span class="line"><span style="color:#FF79C6"> fn</span><span style="color:#50FA7B"> unsubscribe_then</span><span style="color:#F8F8F2">(</span><span style="color:#BD93F9;font-style:italic">self</span><span style="color:#F8F8F2">, on_end</span><span style="color:#FF79C6">:</span><span style="color:#8BE9FD;font-style:italic"> OnEndedCallback</span><span style="color:#F8F8F2"><</span><span style="color:#BD93F9;font-style:italic">Self</span><span style="color:#FF79C6">::</span><span style="color:#8BE9FD;font-style:italic">Module</span><span style="color:#F8F8F2">>) </span><span style="color:#FF79C6">-></span><span style="color:#FF79C6"> crate::</span><span style="color:#8BE9FD;font-style:italic">Result</span><span style="color:#F8F8F2"><()>;</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#6272A4"> /// Unsubscribe from the query controlled by this `SubscriptionHandle`.</span></span>
|
||
<span class="line"><span style="color:#6272A4"> /// Returns an error if the subscription is already ended,</span></span>
|
||
<span class="line"><span style="color:#6272A4"> /// or if unsubscribe has already been called.</span></span>
|
||
<span class="line"><span style="color:#FF79C6"> fn</span><span style="color:#50FA7B"> unsubscribe</span><span style="color:#F8F8F2">(</span><span style="color:#BD93F9;font-style:italic">self</span><span style="color:#F8F8F2">) </span><span style="color:#FF79C6">-></span><span style="color:#FF79C6"> crate::</span><span style="color:#8BE9FD;font-style:italic">Result</span><span style="color:#F8F8F2"><()>;</span></span>
|
||
<span class="line"><span style="color:#F8F8F2">}</span></span></code></pre></div><div role="tabpanel" class="tabItem_sydm" hidden=""><pre tabindex="0" class="codeBlockStandalone_pMzE thin-scrollbar codeBlockContainer_HZVP theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><code class="codeBlockLines_ckKi"><span class="line"><span style="color:#FF79C6"> public</span><span style="color:#FF79C6"> class</span><span style="color:#8BE9FD"> SubscriptionHandle</span><span style="color:#F8F8F2"><</span><span style="color:#FFB86C;font-style:italic">SubscriptionEventContext</span><span style="color:#F8F8F2">, </span><span style="color:#FFB86C;font-style:italic">ErrorContext</span><span style="color:#F8F8F2">> : </span><span style="color:#8BE9FD;font-style:italic">ISubscriptionHandle</span></span>
|
||
<span class="line"><span style="color:#FF79C6"> where</span><span style="color:#FFB86C;font-style:italic"> SubscriptionEventContext</span><span style="color:#F8F8F2"> : </span><span style="color:#8BE9FD;font-style:italic">ISubscriptionEventContext</span></span>
|
||
<span class="line"><span style="color:#FF79C6"> where</span><span style="color:#FFB86C;font-style:italic"> ErrorContext</span><span style="color:#F8F8F2"> : </span><span style="color:#8BE9FD;font-style:italic">IErrorContext</span></span>
|
||
<span class="line"><span style="color:#F8F8F2"> {</span></span>
|
||
<span class="line"><span style="color:#6272A4"> /// </span><span style="color:#F8F8F2"><</span><span style="color:#FF79C6">summary</span><span style="color:#F8F8F2">></span></span>
|
||
<span class="line"><span style="color:#6272A4"> /// Whether the subscription has ended.</span></span>
|
||
<span class="line"><span style="color:#6272A4"> /// </span><span style="color:#F8F8F2"></</span><span style="color:#FF79C6">summary</span><span style="color:#F8F8F2">></span></span>
|
||
<span class="line"><span style="color:#FF79C6"> public</span><span style="color:#FF79C6"> bool</span><span style="color:#F8F8F2"> IsEnded;</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#6272A4"> /// </span><span style="color:#F8F8F2"><</span><span style="color:#FF79C6">summary</span><span style="color:#F8F8F2">></span></span>
|
||
<span class="line"><span style="color:#6272A4"> /// Whether the subscription is active.</span></span>
|
||
<span class="line"><span style="color:#6272A4"> /// </span><span style="color:#F8F8F2"></</span><span style="color:#FF79C6">summary</span><span style="color:#F8F8F2">></span></span>
|
||
<span class="line"><span style="color:#FF79C6"> public</span><span style="color:#FF79C6"> bool</span><span style="color:#F8F8F2"> IsActive;</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#6272A4"> /// </span><span style="color:#F8F8F2"><</span><span style="color:#FF79C6">summary</span><span style="color:#F8F8F2">></span></span>
|
||
<span class="line"><span style="color:#6272A4"> /// Unsubscribe from the query controlled by this subscription handle.</span></span>
|
||
<span class="line"><span style="color:#6272A4"> ///</span></span>
|
||
<span class="line"><span style="color:#6272A4"> /// Calling this more than once will result in an exception.</span></span>
|
||
<span class="line"><span style="color:#6272A4"> /// </span><span style="color:#F8F8F2"></</span><span style="color:#FF79C6">summary</span><span style="color:#F8F8F2">></span></span>
|
||
<span class="line"><span style="color:#FF79C6"> public</span><span style="color:#FF79C6"> void</span><span style="color:#50FA7B"> Unsubscribe</span><span style="color:#F8F8F2">();</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#6272A4"> /// </span><span style="color:#F8F8F2"><</span><span style="color:#FF79C6">summary</span><span style="color:#F8F8F2">></span></span>
|
||
<span class="line"><span style="color:#6272A4"> /// Unsubscribe from the query controlled by this subscription handle,</span></span>
|
||
<span class="line"><span style="color:#6272A4"> /// and call onEnded when its rows are removed from the client cache.</span></span>
|
||
<span class="line"><span style="color:#6272A4"> /// </span><span style="color:#F8F8F2"></</span><span style="color:#FF79C6">summary</span><span style="color:#F8F8F2">></span></span>
|
||
<span class="line"><span style="color:#FF79C6"> public</span><span style="color:#FF79C6"> void</span><span style="color:#50FA7B"> UnsubscribeThen</span><span style="color:#F8F8F2">(</span><span style="color:#8BE9FD;font-style:italic">Action</span><span style="color:#F8F8F2"><</span><span style="color:#8BE9FD;font-style:italic">SubscriptionEventContext</span><span style="color:#F8F8F2">>? </span><span style="color:#FFB86C;font-style:italic">onEnded</span><span style="color:#F8F8F2">);</span></span>
|
||
<span class="line"><span style="color:#F8F8F2"> }</span></span></code></pre></div></div></div>
|
||
<p>When you register a subscription, you receive a <code>SubscriptionHandle</code>.
|
||
A <code>SubscriptionHandle</code> manages the lifecycle of each subscription you register.
|
||
In particular, it provides methods to check the status of the subscription and to unsubscribe if necessary.
|
||
Because each subscription has its own independently managed lifetime,
|
||
clients can dynamically subscribe to different subsets of the database as their application requires.</p>
|
||
<h3 class="anchor anchorWithStickyNavbar_wKCU" id="example-usage-1">Example Usage<a href="#example-usage-1" class="hash-link" aria-label="Direct link to Example Usage" title="Direct link to Example Usage" translate="no"></a></h3>
|
||
<div class="theme-tabs-container tabs-container tabList_MbSD"><ul role="tablist" aria-orientation="horizontal" class="tabs"><li role="tab" tabindex="0" aria-selected="true" class="tabs__item tabItem_Ssy3 tabs__item--active">Rust</li><li role="tab" tabindex="-1" aria-selected="false" class="tabs__item tabItem_Ssy3">C#</li></ul><div class="margin-top--md"><div role="tabpanel" class="tabItem_sydm"><p>Consider a game client that displays shop items and discounts based on a player's level.
|
||
You subscribe to <code>shop_items</code> and <code>shop_discounts</code> when a player is at level 5:</p><pre tabindex="0" class="codeBlockStandalone_pMzE thin-scrollbar codeBlockContainer_HZVP theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><code class="codeBlockLines_ckKi"><span class="line"><span style="color:#FF79C6">let</span><span style="color:#F8F8F2"> conn</span><span style="color:#FF79C6">:</span><span style="color:#8BE9FD;font-style:italic"> DbConnection</span><span style="color:#FF79C6"> =</span><span style="color:#50FA7B"> connect_to_db</span><span style="color:#F8F8F2">();</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#FF79C6">let</span><span style="color:#F8F8F2"> shop_items_subscription </span><span style="color:#FF79C6">=</span><span style="color:#F8F8F2"> conn</span></span>
|
||
<span class="line"><span style="color:#FF79C6"> .</span><span style="color:#50FA7B">subscription_builder</span><span style="color:#F8F8F2">()</span></span>
|
||
<span class="line"><span style="color:#FF79C6"> .</span><span style="color:#50FA7B">on_applied</span><span style="color:#F8F8F2">(</span><span style="color:#FF79C6">|</span><span style="color:#F8F8F2">ctx</span><span style="color:#FF79C6">|</span><span style="color:#F8F8F2"> { </span><span style="color:#6272A4">/* handle applied state */</span><span style="color:#F8F8F2"> })</span></span>
|
||
<span class="line"><span style="color:#FF79C6"> .</span><span style="color:#50FA7B">on_error</span><span style="color:#F8F8F2">(</span><span style="color:#FF79C6">|</span><span style="color:#F8F8F2">error_ctx, error</span><span style="color:#FF79C6">|</span><span style="color:#F8F8F2"> { </span><span style="color:#6272A4">/* handle error */</span><span style="color:#F8F8F2"> })</span></span>
|
||
<span class="line"><span style="color:#FF79C6"> .</span><span style="color:#50FA7B">subscribe</span><span style="color:#F8F8F2">([</span></span>
|
||
<span class="line"><span style="color:#F1FA8C"> "SELECT * FROM shop_items WHERE required_level <= 5"</span><span style="color:#F8F8F2">,</span></span>
|
||
<span class="line"><span style="color:#F1FA8C"> "SELECT * FROM shop_discounts WHERE required_level <= 5"</span><span style="color:#F8F8F2">,</span></span>
|
||
<span class="line"><span style="color:#F8F8F2"> ]);</span></span></code></pre><p>Later, when the player reaches level 6 and new items become available,
|
||
you can subscribe to the new queries and unsubscribe from the old ones:</p><pre tabindex="0" class="codeBlockStandalone_pMzE thin-scrollbar codeBlockContainer_HZVP theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><code class="codeBlockLines_ckKi"><span class="line"><span style="color:#FF79C6">let</span><span style="color:#F8F8F2"> new_shop_items_subscription </span><span style="color:#FF79C6">=</span><span style="color:#F8F8F2"> conn</span></span>
|
||
<span class="line"><span style="color:#FF79C6"> .</span><span style="color:#50FA7B">subscription_builder</span><span style="color:#F8F8F2">()</span></span>
|
||
<span class="line"><span style="color:#FF79C6"> .</span><span style="color:#50FA7B">on_applied</span><span style="color:#F8F8F2">(</span><span style="color:#FF79C6">|</span><span style="color:#F8F8F2">ctx</span><span style="color:#FF79C6">|</span><span style="color:#F8F8F2"> { </span><span style="color:#6272A4">/* handle applied state */</span><span style="color:#F8F8F2"> })</span></span>
|
||
<span class="line"><span style="color:#FF79C6"> .</span><span style="color:#50FA7B">on_error</span><span style="color:#F8F8F2">(</span><span style="color:#FF79C6">|</span><span style="color:#F8F8F2">error_ctx, error</span><span style="color:#FF79C6">|</span><span style="color:#F8F8F2"> { </span><span style="color:#6272A4">/* handle error */</span><span style="color:#F8F8F2"> })</span></span>
|
||
<span class="line"><span style="color:#FF79C6"> .</span><span style="color:#50FA7B">subscribe</span><span style="color:#F8F8F2">([</span></span>
|
||
<span class="line"><span style="color:#F1FA8C"> "SELECT * FROM shop_items WHERE required_level <= 6"</span><span style="color:#F8F8F2">,</span></span>
|
||
<span class="line"><span style="color:#F1FA8C"> "SELECT * FROM shop_discounts WHERE required_level <= 6"</span><span style="color:#F8F8F2">,</span></span>
|
||
<span class="line"><span style="color:#F8F8F2"> ]);</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#FF79C6">if</span><span style="color:#F8F8F2"> shop_items_subscription</span><span style="color:#FF79C6">.</span><span style="color:#50FA7B">is_active</span><span style="color:#F8F8F2">() {</span></span>
|
||
<span class="line"><span style="color:#F8F8F2"> shop_items_subscription</span></span>
|
||
<span class="line"><span style="color:#FF79C6"> .</span><span style="color:#50FA7B">unsubscribe</span><span style="color:#F8F8F2">()</span></span>
|
||
<span class="line"><span style="color:#FF79C6"> .</span><span style="color:#50FA7B">expect</span><span style="color:#F8F8F2">(</span><span style="color:#F1FA8C">"Unsubscribing from shop_items failed"</span><span style="color:#F8F8F2">);</span></span>
|
||
<span class="line"><span style="color:#F8F8F2">}</span></span></code></pre><p>All other subscriptions continue to remain in effect.</p></div><div role="tabpanel" class="tabItem_sydm" hidden=""><p>Consider a game client that displays shop items and discounts based on a player's level.
|
||
You subscribe to <code>shop_items</code> and <code>shop_discounts</code> when a player is at level 5:</p><pre tabindex="0" class="codeBlockStandalone_pMzE thin-scrollbar codeBlockContainer_HZVP theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><code class="codeBlockLines_ckKi"><span class="line"><span style="color:#FF79C6">var</span><span style="color:#F8F8F2"> conn </span><span style="color:#FF79C6">=</span><span style="color:#50FA7B"> ConnectToDB</span><span style="color:#F8F8F2">();</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#FF79C6">var</span><span style="color:#F8F8F2"> shopItemsSubscription </span><span style="color:#FF79C6">=</span><span style="color:#F8F8F2"> conn</span></span>
|
||
<span class="line"><span style="color:#F8F8F2"> .</span><span style="color:#50FA7B">SubscriptionBuilder</span><span style="color:#F8F8F2">()</span></span>
|
||
<span class="line"><span style="color:#F8F8F2"> .</span><span style="color:#50FA7B">OnApplied</span><span style="color:#F8F8F2">((</span><span style="color:#FFB86C;font-style:italic">ctx</span><span style="color:#F8F8F2">) </span><span style="color:#FF79C6">=></span><span style="color:#F8F8F2"> { </span><span style="color:#6272A4">/* handle applied state */</span><span style="color:#F8F8F2"> })</span></span>
|
||
<span class="line"><span style="color:#F8F8F2"> .</span><span style="color:#50FA7B">OnError</span><span style="color:#F8F8F2">((</span><span style="color:#FFB86C;font-style:italic">errorCtx</span><span style="color:#F8F8F2">, </span><span style="color:#FFB86C;font-style:italic">error</span><span style="color:#F8F8F2">) </span><span style="color:#FF79C6">=></span><span style="color:#F8F8F2"> { </span><span style="color:#6272A4">/* handle error */</span><span style="color:#F8F8F2"> })</span></span>
|
||
<span class="line"><span style="color:#F8F8F2"> .</span><span style="color:#50FA7B">Subscribe</span><span style="color:#F8F8F2">(</span><span style="color:#FF79C6">new</span><span style="color:#FF79C6"> string</span><span style="color:#F8F8F2">[] {</span></span>
|
||
<span class="line"><span style="color:#E9F284"> "</span><span style="color:#F1FA8C">SELECT * FROM shop_items WHERE required_level <= 5</span><span style="color:#E9F284">"</span><span style="color:#F8F8F2">,</span></span>
|
||
<span class="line"><span style="color:#E9F284"> "</span><span style="color:#F1FA8C">SELECT * FROM shop_discounts WHERE required_level <= 5</span><span style="color:#E9F284">"</span><span style="color:#F8F8F2">,</span></span>
|
||
<span class="line"><span style="color:#F8F8F2"> });</span></span></code></pre><p>Later, when the player reaches level 6 and new items become available,
|
||
you can subscribe to the new queries and unsubscribe from the old ones:</p><pre tabindex="0" class="codeBlockStandalone_pMzE thin-scrollbar codeBlockContainer_HZVP theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><code class="codeBlockLines_ckKi"><span class="line"><span style="color:#FF79C6">var</span><span style="color:#F8F8F2"> newShopItemsSubscription </span><span style="color:#FF79C6">=</span><span style="color:#F8F8F2"> conn</span></span>
|
||
<span class="line"><span style="color:#F8F8F2"> .</span><span style="color:#50FA7B">SubscriptionBuilder</span><span style="color:#F8F8F2">()</span></span>
|
||
<span class="line"><span style="color:#F8F8F2"> .</span><span style="color:#50FA7B">OnApplied</span><span style="color:#F8F8F2">((</span><span style="color:#FFB86C;font-style:italic">ctx</span><span style="color:#F8F8F2">) </span><span style="color:#FF79C6">=></span><span style="color:#F8F8F2"> { </span><span style="color:#6272A4">/* handle applied state */</span><span style="color:#F8F8F2"> })</span></span>
|
||
<span class="line"><span style="color:#F8F8F2"> .</span><span style="color:#50FA7B">OnError</span><span style="color:#F8F8F2">((</span><span style="color:#FFB86C;font-style:italic">errorCtx</span><span style="color:#F8F8F2">, </span><span style="color:#FFB86C;font-style:italic">error</span><span style="color:#F8F8F2">) </span><span style="color:#FF79C6">=></span><span style="color:#F8F8F2"> { </span><span style="color:#6272A4">/* handle error */</span><span style="color:#F8F8F2"> })</span></span>
|
||
<span class="line"><span style="color:#F8F8F2"> .</span><span style="color:#50FA7B">Subscribe</span><span style="color:#F8F8F2">(</span><span style="color:#FF79C6">new</span><span style="color:#FF79C6"> string</span><span style="color:#F8F8F2">[] {</span></span>
|
||
<span class="line"><span style="color:#E9F284"> "</span><span style="color:#F1FA8C">SELECT * FROM shop_items WHERE required_level <= 6</span><span style="color:#E9F284">"</span><span style="color:#F8F8F2">,</span></span>
|
||
<span class="line"><span style="color:#E9F284"> "</span><span style="color:#F1FA8C">SELECT * FROM shop_discounts WHERE required_level <= 6</span><span style="color:#E9F284">"</span><span style="color:#F8F8F2">,</span></span>
|
||
<span class="line"><span style="color:#F8F8F2"> });</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#FF79C6">if</span><span style="color:#F8F8F2"> (shopItemsSubscription.IsActive)</span></span>
|
||
<span class="line"><span style="color:#F8F8F2">{</span></span>
|
||
<span class="line"><span style="color:#F8F8F2"> shopItemsSubscription.</span><span style="color:#50FA7B">Unsubscribe</span><span style="color:#F8F8F2">();</span></span>
|
||
<span class="line"><span style="color:#F8F8F2">}</span></span></code></pre><p>All other subscriptions continue to remain in effect.</p></div></div></div>
|
||
<h2 class="anchor anchorWithStickyNavbar_wKCU" id="best-practices-for-optimizing-server-compute-and-reducing-serialization-overhead">Best Practices for Optimizing Server Compute and Reducing Serialization Overhead<a href="#best-practices-for-optimizing-server-compute-and-reducing-serialization-overhead" class="hash-link" aria-label="Direct link to Best Practices for Optimizing Server Compute and Reducing Serialization Overhead" title="Direct link to Best Practices for Optimizing Server Compute and Reducing Serialization Overhead" translate="no"></a></h2>
|
||
<h3 class="anchor anchorWithStickyNavbar_wKCU" id="1-writing-efficient-sql-queries">1. Writing Efficient SQL Queries<a href="#1-writing-efficient-sql-queries" class="hash-link" aria-label="Direct link to 1. Writing Efficient SQL Queries" title="Direct link to 1. Writing Efficient SQL Queries" translate="no"></a></h3>
|
||
<p>For writing efficient SQL queries, see our <a href="/sql#best-practices-for-performance-and-scalability">SQL Best Practices Guide</a>.</p>
|
||
<h3 class="anchor anchorWithStickyNavbar_wKCU" id="2-group-subscriptions-with-the-same-lifetime-together">2. Group Subscriptions with the Same Lifetime Together<a href="#2-group-subscriptions-with-the-same-lifetime-together" class="hash-link" aria-label="Direct link to 2. Group Subscriptions with the Same Lifetime Together" title="Direct link to 2. Group Subscriptions with the Same Lifetime Together" translate="no"></a></h3>
|
||
<p>Subscriptions with the same lifetime should be grouped together.</p>
|
||
<p>For example, you may have certain data that is required for the lifetime of your application,
|
||
but you may have other data that is only sometimes required by your application.</p>
|
||
<p>By managing these sets as two independent subscriptions,
|
||
your application can subscribe and unsubscribe from the latter,
|
||
without needlessly unsubscribing and resubscribing to the former.</p>
|
||
<p>This will improve throughput by reducing the amount of data transferred from the database to your application.</p>
|
||
<h4 class="anchor anchorWithStickyNavbar_wKCU" id="example">Example<a href="#example" class="hash-link" aria-label="Direct link to Example" title="Direct link to Example" translate="no"></a></h4>
|
||
<div class="theme-tabs-container tabs-container tabList_MbSD"><ul role="tablist" aria-orientation="horizontal" class="tabs"><li role="tab" tabindex="0" aria-selected="true" class="tabs__item tabItem_Ssy3 tabs__item--active">Rust</li><li role="tab" tabindex="-1" aria-selected="false" class="tabs__item tabItem_Ssy3">C#</li></ul><div class="margin-top--md"><div role="tabpanel" class="tabItem_sydm"><pre tabindex="0" class="codeBlockStandalone_pMzE thin-scrollbar codeBlockContainer_HZVP theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><code class="codeBlockLines_ckKi"><span class="line"><span style="color:#FF79C6">let</span><span style="color:#F8F8F2"> conn</span><span style="color:#FF79C6">:</span><span style="color:#8BE9FD;font-style:italic"> DbConnection</span><span style="color:#FF79C6"> =</span><span style="color:#50FA7B"> connect_to_db</span><span style="color:#F8F8F2">();</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#6272A4">// Never need to unsubscribe from global subscriptions</span></span>
|
||
<span class="line"><span style="color:#FF79C6">let</span><span style="color:#F8F8F2"> global_subscriptions </span><span style="color:#FF79C6">=</span><span style="color:#F8F8F2"> conn</span></span>
|
||
<span class="line"><span style="color:#FF79C6"> .</span><span style="color:#50FA7B">subscription_builder</span><span style="color:#F8F8F2">()</span></span>
|
||
<span class="line"><span style="color:#FF79C6"> .</span><span style="color:#50FA7B">subscribe</span><span style="color:#F8F8F2">([</span></span>
|
||
<span class="line"><span style="color:#6272A4"> // Global messages the client should always display</span></span>
|
||
<span class="line"><span style="color:#F1FA8C"> "SELECT * FROM announcements"</span><span style="color:#F8F8F2">,</span></span>
|
||
<span class="line"><span style="color:#6272A4"> // A description of rewards for in-game achievements</span></span>
|
||
<span class="line"><span style="color:#F1FA8C"> "SELECT * FROM badges"</span><span style="color:#F8F8F2">,</span></span>
|
||
<span class="line"><span style="color:#F8F8F2"> ]);</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#6272A4">// May unsubscribe to shop_items as player advances</span></span>
|
||
<span class="line"><span style="color:#FF79C6">let</span><span style="color:#F8F8F2"> shop_subscription </span><span style="color:#FF79C6">=</span><span style="color:#F8F8F2"> conn</span></span>
|
||
<span class="line"><span style="color:#FF79C6"> .</span><span style="color:#50FA7B">subscription_builder</span><span style="color:#F8F8F2">()</span></span>
|
||
<span class="line"><span style="color:#FF79C6"> .</span><span style="color:#50FA7B">subscribe</span><span style="color:#F8F8F2">([</span></span>
|
||
<span class="line"><span style="color:#F1FA8C"> "SELECT * FROM shop_items WHERE required_level <= 5"</span><span style="color:#F8F8F2">,</span></span>
|
||
<span class="line"><span style="color:#F8F8F2"> ]);</span></span></code></pre></div><div role="tabpanel" class="tabItem_sydm" hidden=""><pre tabindex="0" class="codeBlockStandalone_pMzE thin-scrollbar codeBlockContainer_HZVP theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><code class="codeBlockLines_ckKi"><span class="line"><span style="color:#FF79C6">var</span><span style="color:#F8F8F2"> conn </span><span style="color:#FF79C6">=</span><span style="color:#50FA7B"> ConnectToDB</span><span style="color:#F8F8F2">();</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#6272A4">// Never need to unsubscribe from global subscriptions</span></span>
|
||
<span class="line"><span style="color:#FF79C6">var</span><span style="color:#F8F8F2"> globalSubscriptions </span><span style="color:#FF79C6">=</span><span style="color:#F8F8F2"> conn</span></span>
|
||
<span class="line"><span style="color:#F8F8F2"> .</span><span style="color:#50FA7B">SubscriptionBuilder</span><span style="color:#F8F8F2">()</span></span>
|
||
<span class="line"><span style="color:#F8F8F2"> .</span><span style="color:#50FA7B">Subscribe</span><span style="color:#F8F8F2">(</span><span style="color:#FF79C6">new</span><span style="color:#FF79C6"> string</span><span style="color:#F8F8F2">[] {</span></span>
|
||
<span class="line"><span style="color:#6272A4"> // Global messages the client should always display</span></span>
|
||
<span class="line"><span style="color:#E9F284"> "</span><span style="color:#F1FA8C">SELECT * FROM announcements</span><span style="color:#E9F284">"</span><span style="color:#F8F8F2">,</span></span>
|
||
<span class="line"><span style="color:#6272A4"> // A description of rewards for in-game achievements</span></span>
|
||
<span class="line"><span style="color:#E9F284"> "</span><span style="color:#F1FA8C">SELECT * FROM badges</span><span style="color:#E9F284">"</span><span style="color:#F8F8F2">,</span></span>
|
||
<span class="line"><span style="color:#F8F8F2"> });</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#6272A4">// May unsubscribe to shop_items as player advances</span></span>
|
||
<span class="line"><span style="color:#FF79C6">var</span><span style="color:#F8F8F2"> shopSubscription </span><span style="color:#FF79C6">=</span><span style="color:#F8F8F2"> conn</span></span>
|
||
<span class="line"><span style="color:#F8F8F2"> .</span><span style="color:#50FA7B">SubscriptionBuilder</span><span style="color:#F8F8F2">()</span></span>
|
||
<span class="line"><span style="color:#F8F8F2"> .</span><span style="color:#50FA7B">Subscribe</span><span style="color:#F8F8F2">(</span><span style="color:#FF79C6">new</span><span style="color:#FF79C6"> string</span><span style="color:#F8F8F2">[] {</span></span>
|
||
<span class="line"><span style="color:#E9F284"> "</span><span style="color:#F1FA8C">SELECT * FROM shop_items WHERE required_level <= 5</span><span style="color:#E9F284">"</span></span>
|
||
<span class="line"><span style="color:#F8F8F2"> });</span></span></code></pre></div></div></div>
|
||
<h3 class="anchor anchorWithStickyNavbar_wKCU" id="3-subscribe-before-unsubscribing">3. Subscribe Before Unsubscribing<a href="#3-subscribe-before-unsubscribing" class="hash-link" aria-label="Direct link to 3. Subscribe Before Unsubscribing" title="Direct link to 3. Subscribe Before Unsubscribing" translate="no"></a></h3>
|
||
<p>If you want to update or modify a subscription by dropping it and subscribing to a new set,
|
||
you should subscribe to the new set before unsubscribing from the old one.</p>
|
||
<p>This is because SpacetimeDB subscriptions are zero-copy.
|
||
Subscribing to the same query more than once doesn't incur additional processing or serialization overhead.
|
||
Likewise, if a query is subscribed to more than once,
|
||
unsubscribing from it does not result in any server processing or data serializtion.</p>
|
||
<h4 class="anchor anchorWithStickyNavbar_wKCU" id="example-1">Example<a href="#example-1" class="hash-link" aria-label="Direct link to Example" title="Direct link to Example" translate="no"></a></h4>
|
||
<div class="theme-tabs-container tabs-container tabList_MbSD"><ul role="tablist" aria-orientation="horizontal" class="tabs"><li role="tab" tabindex="0" aria-selected="true" class="tabs__item tabItem_Ssy3 tabs__item--active">Rust</li><li role="tab" tabindex="-1" aria-selected="false" class="tabs__item tabItem_Ssy3">C#</li></ul><div class="margin-top--md"><div role="tabpanel" class="tabItem_sydm"><pre tabindex="0" class="codeBlockStandalone_pMzE thin-scrollbar codeBlockContainer_HZVP theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><code class="codeBlockLines_ckKi"><span class="line"><span style="color:#FF79C6">let</span><span style="color:#F8F8F2"> conn</span><span style="color:#FF79C6">:</span><span style="color:#8BE9FD;font-style:italic"> DbConnection</span><span style="color:#FF79C6"> =</span><span style="color:#50FA7B"> connect_to_db</span><span style="color:#F8F8F2">();</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#6272A4">// Initial subscription: player at level 5.</span></span>
|
||
<span class="line"><span style="color:#FF79C6">let</span><span style="color:#F8F8F2"> shop_subscription </span><span style="color:#FF79C6">=</span><span style="color:#F8F8F2"> conn</span></span>
|
||
<span class="line"><span style="color:#FF79C6"> .</span><span style="color:#50FA7B">subscription_builder</span><span style="color:#F8F8F2">()</span></span>
|
||
<span class="line"><span style="color:#FF79C6"> .</span><span style="color:#50FA7B">subscribe</span><span style="color:#F8F8F2">([</span></span>
|
||
<span class="line"><span style="color:#6272A4"> // For displaying the price of shop items in the player's currency of choice</span></span>
|
||
<span class="line"><span style="color:#F1FA8C"> "SELECT * FROM exchange_rates"</span><span style="color:#F8F8F2">,</span></span>
|
||
<span class="line"><span style="color:#F1FA8C"> "SELECT * FROM shop_items WHERE required_level <= 5"</span><span style="color:#F8F8F2">,</span></span>
|
||
<span class="line"><span style="color:#F8F8F2"> ]);</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#6272A4">// New subscription: player now at level 6, which overlaps with the previous query.</span></span>
|
||
<span class="line"><span style="color:#FF79C6">let</span><span style="color:#F8F8F2"> new_shop_subscription </span><span style="color:#FF79C6">=</span><span style="color:#F8F8F2"> conn</span></span>
|
||
<span class="line"><span style="color:#FF79C6"> .</span><span style="color:#50FA7B">subscription_builder</span><span style="color:#F8F8F2">()</span></span>
|
||
<span class="line"><span style="color:#FF79C6"> .</span><span style="color:#50FA7B">subscribe</span><span style="color:#F8F8F2">([</span></span>
|
||
<span class="line"><span style="color:#6272A4"> // For displaying the price of shop items in the player's currency of choice</span></span>
|
||
<span class="line"><span style="color:#F1FA8C"> "SELECT * FROM exchange_rates"</span><span style="color:#F8F8F2">,</span></span>
|
||
<span class="line"><span style="color:#F1FA8C"> "SELECT * FROM shop_items WHERE required_level <= 6"</span><span style="color:#F8F8F2">,</span></span>
|
||
<span class="line"><span style="color:#F8F8F2"> ]);</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#6272A4">// Unsubscribe from the old subscription once the new one is active.</span></span>
|
||
<span class="line"><span style="color:#FF79C6">if</span><span style="color:#F8F8F2"> shop_subscription</span><span style="color:#FF79C6">.</span><span style="color:#50FA7B">is_active</span><span style="color:#F8F8F2">() {</span></span>
|
||
<span class="line"><span style="color:#F8F8F2"> shop_subscription</span><span style="color:#FF79C6">.</span><span style="color:#50FA7B">unsubscribe</span><span style="color:#F8F8F2">();</span></span>
|
||
<span class="line"><span style="color:#F8F8F2">}</span></span></code></pre></div><div role="tabpanel" class="tabItem_sydm" hidden=""><pre tabindex="0" class="codeBlockStandalone_pMzE thin-scrollbar codeBlockContainer_HZVP theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><code class="codeBlockLines_ckKi"><span class="line"><span style="color:#FF79C6">var</span><span style="color:#F8F8F2"> conn </span><span style="color:#FF79C6">=</span><span style="color:#50FA7B"> ConnectToDB</span><span style="color:#F8F8F2">();</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#6272A4">// Initial subscription: player at level 5.</span></span>
|
||
<span class="line"><span style="color:#FF79C6">var</span><span style="color:#F8F8F2"> shopSubscription </span><span style="color:#FF79C6">=</span><span style="color:#F8F8F2"> conn</span></span>
|
||
<span class="line"><span style="color:#F8F8F2"> .</span><span style="color:#50FA7B">SubscriptionBuilder</span><span style="color:#F8F8F2">()</span></span>
|
||
<span class="line"><span style="color:#F8F8F2"> .</span><span style="color:#50FA7B">Subscribe</span><span style="color:#F8F8F2">(</span><span style="color:#FF79C6">new</span><span style="color:#FF79C6"> string</span><span style="color:#F8F8F2">[] {</span></span>
|
||
<span class="line"><span style="color:#6272A4"> // For displaying the price of shop items in the player's currency of choice</span></span>
|
||
<span class="line"><span style="color:#E9F284"> "</span><span style="color:#F1FA8C">SELECT * FROM exchange_rates</span><span style="color:#E9F284">"</span><span style="color:#F8F8F2">,</span></span>
|
||
<span class="line"><span style="color:#E9F284"> "</span><span style="color:#F1FA8C">SELECT * FROM shop_items WHERE required_level <= 5</span><span style="color:#E9F284">"</span></span>
|
||
<span class="line"><span style="color:#F8F8F2"> });</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#6272A4">// New subscription: player now at level 6, which overlaps with the previous query.</span></span>
|
||
<span class="line"><span style="color:#FF79C6">var</span><span style="color:#F8F8F2"> newShopSubscription </span><span style="color:#FF79C6">=</span><span style="color:#F8F8F2"> conn</span></span>
|
||
<span class="line"><span style="color:#F8F8F2"> .</span><span style="color:#50FA7B">SubscriptionBuilder</span><span style="color:#F8F8F2">()</span></span>
|
||
<span class="line"><span style="color:#F8F8F2"> .</span><span style="color:#50FA7B">Subscribe</span><span style="color:#F8F8F2">(</span><span style="color:#FF79C6">new</span><span style="color:#FF79C6"> string</span><span style="color:#F8F8F2">[] {</span></span>
|
||
<span class="line"><span style="color:#6272A4"> // For displaying the price of shop items in the player's currency of choice</span></span>
|
||
<span class="line"><span style="color:#E9F284"> "</span><span style="color:#F1FA8C">SELECT * FROM exchange_rates</span><span style="color:#E9F284">"</span><span style="color:#F8F8F2">,</span></span>
|
||
<span class="line"><span style="color:#E9F284"> "</span><span style="color:#F1FA8C">SELECT * FROM shop_items WHERE required_level <= 6</span><span style="color:#E9F284">"</span></span>
|
||
<span class="line"><span style="color:#F8F8F2"> });</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#6272A4">// Unsubscribe from the old subscription once the new one is in place.</span></span>
|
||
<span class="line"><span style="color:#FF79C6">if</span><span style="color:#F8F8F2"> (shopSubscription.IsActive)</span></span>
|
||
<span class="line"><span style="color:#F8F8F2">{</span></span>
|
||
<span class="line"><span style="color:#F8F8F2"> shopSubscription.</span><span style="color:#50FA7B">Unsubscribe</span><span style="color:#F8F8F2">();</span></span>
|
||
<span class="line"><span style="color:#F8F8F2">}</span></span></code></pre></div></div></div>
|
||
<h3 class="anchor anchorWithStickyNavbar_wKCU" id="4-avoid-overlapping-queries">4. Avoid Overlapping Queries<a href="#4-avoid-overlapping-queries" class="hash-link" aria-label="Direct link to 4. Avoid Overlapping Queries" title="Direct link to 4. Avoid Overlapping Queries" translate="no"></a></h3>
|
||
<p>This refers to distinct queries that return intersecting data sets,
|
||
which can result in the server processing and serializing the same row multiple times.
|
||
While SpacetimeDB can manage this redundancy, it may lead to unnecessary inefficiencies.</p>
|
||
<p>Consider the following two queries:</p>
|
||
<pre tabindex="0" class="codeBlockStandalone_pMzE thin-scrollbar codeBlockContainer_HZVP theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><code class="codeBlockLines_ckKi"><span class="line"><span style="color:#FF79C6">SELECT</span><span style="color:#FF79C6"> *</span><span style="color:#FF79C6"> FROM</span><span style="color:#F8F8F2"> User</span></span>
|
||
<span class="line"><span style="color:#FF79C6">SELECT</span><span style="color:#FF79C6"> *</span><span style="color:#FF79C6"> FROM</span><span style="color:#F8F8F2"> User </span><span style="color:#FF79C6">WHERE</span><span style="color:#F8F8F2"> id </span><span style="color:#FF79C6">=</span><span style="color:#BD93F9"> 5</span></span></code></pre>
|
||
<p>If <code>User.id</code> is a unique or primary key column,
|
||
the cost of subscribing to both queries is minimal.
|
||
This is because the server will use an index when processing the 2nd query,
|
||
and it will only serialize a single row for the 2nd query.</p>
|
||
<p>In contrast, consider these two queries:</p>
|
||
<pre tabindex="0" class="codeBlockStandalone_pMzE thin-scrollbar codeBlockContainer_HZVP theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><code class="codeBlockLines_ckKi"><span class="line"><span style="color:#FF79C6">SELECT</span><span style="color:#FF79C6"> *</span><span style="color:#FF79C6"> FROM</span><span style="color:#F8F8F2"> User</span></span>
|
||
<span class="line"><span style="color:#FF79C6">SELECT</span><span style="color:#FF79C6"> *</span><span style="color:#FF79C6"> FROM</span><span style="color:#F8F8F2"> User </span><span style="color:#FF79C6">WHERE</span><span style="color:#F8F8F2"> id </span><span style="color:#FF79C6">!=</span><span style="color:#BD93F9"> 5</span></span></code></pre>
|
||
<p>The server must now process each row of the <code>User</code> table twice,
|
||
since the 2nd query cannot be processed using an index.
|
||
It must also serialize all but one row of the <code>User</code> table twice,
|
||
due to the significant overlap between the two queries.</p>
|
||
<p>By following these best practices, you can optimize your data replication strategy and ensure your application remains efficient and responsive.</p></div></article><nav class="docusaurus-mt-lg pagination-nav" aria-label="Docs pages"><a class="pagination-nav__link pagination-nav__link--prev" href="/docs/sql/pg-wire"><div class="pagination-nav__sublabel">Previous</div><div class="pagination-nav__label">PostgreSQL Wire Protocol (PGWire)</div></a><a class="pagination-nav__link pagination-nav__link--next" href="/subscriptions/semantics"><div class="pagination-nav__sublabel">Next</div><div class="pagination-nav__label">Subscription Semantics</div></a></nav></div></div><div class="col col--3"><div class="tableOfContents_Ea_L thin-scrollbar theme-doc-toc-desktop"><ul class="table-of-contents table-of-contents__left-border"><li><a href="#subscriptionbuilder" class="table-of-contents__link toc-highlight">SubscriptionBuilder</a><ul><li><a href="#example-usage" class="table-of-contents__link toc-highlight">Example Usage</a></li></ul></li><li><a href="#subscriptionhandle" class="table-of-contents__link toc-highlight">SubscriptionHandle</a><ul><li><a href="#example-usage-1" class="table-of-contents__link toc-highlight">Example Usage</a></li></ul></li><li><a href="#best-practices-for-optimizing-server-compute-and-reducing-serialization-overhead" class="table-of-contents__link toc-highlight">Best Practices for Optimizing Server Compute and Reducing Serialization Overhead</a><ul><li><a href="#1-writing-efficient-sql-queries" class="table-of-contents__link toc-highlight">1. Writing Efficient SQL Queries</a></li><li><a href="#2-group-subscriptions-with-the-same-lifetime-together" class="table-of-contents__link toc-highlight">2. Group Subscriptions with the Same Lifetime Together</a></li><li><a href="#3-subscribe-before-unsubscribing" class="table-of-contents__link toc-highlight">3. Subscribe Before Unsubscribing</a></li><li><a href="#4-avoid-overlapping-queries" class="table-of-contents__link toc-highlight">4. Avoid Overlapping Queries</a></li></ul></li></ul></div></div></div></div></main></div></div></div><footer class="theme-layout-footer footer"><div class="container container-fluid"></div></footer></div>
|
||
</body>
|
||
</html> |