<turbo-stream action="append" target="posts_list"><template>    <div class="postbit" id="382366" data-post-id="382366">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="derek-zhou" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/derek-zhou/120/19943_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  derek-zhou
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="garrison" data-post="11" data-topic="73767">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/g/3bc359/48.png" class="avatar"> garrison:</div>
<blockquote>
<p>This is difficult to achieve without essentially inventing a database from first principles</p>
</blockquote>
</aside>
<p>If the state is small and performance can be manged by a single GenServer, do you still need a database? I agree true state syncing is much more interesting and useful than message passing.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="382366" data-batch-url="/posts/batch_likers">
                        1
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/support-for-realtime-server-side-updates-and-streams-like-liveview-and-phoenixsync/73767/12">Post #11</a>
	                </div>
	            </div>
              <div id="likers-container-382366" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="382366"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #11"></div>
  </section>
</div>
    <div class="postbit" id="382367" data-post-id="382367">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="garrison" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  garrison
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>This very much depends on context. There are tons of things for which a GenServer is exactly what I would recommend, e.g. for the “realtime cursors” example.</p>
<p>But if you have transactions over application data things start to get tricky. It’s <em>very</em> important that the “log” of events you’re consuming is designed properly. If you can observe transactions out of order, or partially, things go off the rails quickly. The more stuff you do outside of the database, the more room there is for weird consistency bugs.</p>
<p>OTP is very powerful, but it’s also pretty old and lacks good primitives for building distributed systems with strong consistency. Hobbes basically only uses message passing, local name registration, and ETS. Tools like <code>:mnesia</code>, <code>:global</code>, and even <em>monitors</em> are useless in practice.</p>
<p>Also, for a lot of stuff you actually want persistence, and even just safely writing data to disk is <em>so</em> much harder than you probably think. That’s why I’m trying to build a primitive that can take care of that stuff. I think I can lower the barrier to entry <em>substantially</em>.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="382367" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/support-for-realtime-server-side-updates-and-streams-like-liveview-and-phoenixsync/73767/13">Post #12</a>
	                </div>
	            </div>
              <div id="likers-container-382367" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="382367"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #12"></div>
  </section>
</div>
    <div class="postbit" id="382368" data-post-id="382368">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="derek-zhou" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/derek-zhou/120/19943_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  derek-zhou
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="garrison" data-post="13" data-topic="73767">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/g/3bc359/48.png" class="avatar"> garrison:</div>
<blockquote>
<p>But if you have transactions over application data things start to get tricky. It’s <em>very</em> important that the “log” of events you’re consuming is designed properly.</p>
</blockquote>
</aside>
<p>I don’t want a log of events. As you hinted, thing go off rails quickly when network is misbehaving.  I want state deltas:</p>
<ol>
<li>producer advertise new state version</li>
<li>consumer poll for state updates</li>
<li>producer compute state delta and reply to the consumer poll</li>
<li>consumer apply received state delta locally</li>
</ol>
<p>This should be more robust in real world network.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="382368" data-batch-url="/posts/batch_likers">
                        1
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/support-for-realtime-server-side-updates-and-streams-like-liveview-and-phoenixsync/73767/14">Post #13</a>
	                </div>
	            </div>
              <div id="likers-container-382368" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="382368"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #13"></div>
  </section>
</div>
    <div class="postbit" id="382370" data-post-id="382370">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="garrison" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  garrison
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>You can implement state sync over message passing this way, and it’s fine for many things. But the polling increases the latency, so eventually you will start to get <em>ideas</em> about how you could push the state updates to the client directly and you will reinvent the log from first principles as well <img src="https://forum.elixirforum.com/images/emoji/apple/slight_smile.png?v=15" title=":slight_smile:" class="emoji" alt=":slight_smile:" loading="lazy" width="20" height="20"></p>
<p>Producing a delta is also not trivial in practice. You would need to diff the current version against a past version, which means your state is now a persistent data structure. Now you need to invent garbage collection. And how are these objects versioned? Are you guaranteeing linearizability? Etc.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="382370" data-batch-url="/posts/batch_likers">
                        1
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/support-for-realtime-server-side-updates-and-streams-like-liveview-and-phoenixsync/73767/15">Post #14</a>
	                </div>
	            </div>
              <div id="likers-container-382370" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="382370"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #14"></div>
  </section>
</div>
    <div class="postbit" id="382371" data-post-id="382371">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="derek-zhou" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/derek-zhou/120/19943_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  derek-zhou
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="garrison" data-post="15" data-topic="73767">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/g/3bc359/48.png" class="avatar"> garrison:</div>
<blockquote>
<p>which means your state is now a persistent data structure. Now you need to invent garbage collection. And how are these objects versioned? Are you guaranteeing linearizability? Etc.</p>
</blockquote>
</aside>
<p>All of the above is not particularity hard to solve in a small enough scale.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="382371" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/support-for-realtime-server-side-updates-and-streams-like-liveview-and-phoenixsync/73767/16">Post #15</a>
	                </div>
	            </div>
              <div id="likers-container-382371" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="382371"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #15"></div>
  </section>
</div>
    <div class="postbit" id="382391" data-post-id="382391">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="jstimps" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/jstimps/120/37213_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  jstimps
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="garrison" data-post="7" data-topic="73767">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/g/3bc359/48.png" class="avatar"> garrison:</div>
<blockquote>
<p>Postgres can be incrementalized (ElectricSQL does this with WAL parsing) but FoundationDB on the other hand cannot.</p>
</blockquote>
</aside>
<p>It’s true that EctoFDB itself doesn’t attempt to incrementalize FDB state, but I’m not convinced we can say that it cannot be done. FDB can take consistent <a href="https://apple.github.io/foundationdb/backups.html" rel="noopener nofollow ugc">backups</a>, both snapshot (backup agent) and real-time (DR agent). Someone may be able to tap into that system in a novel way. I tried, but ran out of time and focus, and abandoned that effort. It does require reverse engineering the data stream, which is not documented, and could change in any new version. Maybe that is enough to call it impossible. <img src="https://forum.elixirforum.com/images/emoji/apple/slight_smile.png?v=15" title=":slight_smile:" class="emoji" alt=":slight_smile:" loading="lazy" width="20" height="20"></p>
<p>On the other hand, according to my favorite ghost in a jar (Gemini), Postgres does officially support low level WAL parsing, so kudos to them for that.</p>
<p>Will Hobbes incrementalization be based off of a read version? e.g. the client is notified of the content of a change at a particular version stamp, and the client is responsible for understanding the full state at that precise version stamp so that it can consistently process the delta? Or will the communicated delta provide a from-versionstamp and a to-versionstamp, allowing the client to evolve their local state to the new versionstamp?</p>
<p>Am I on the right track here?</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="382391" data-batch-url="/posts/batch_likers">
                        1
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/support-for-realtime-server-side-updates-and-streams-like-liveview-and-phoenixsync/73767/17">Post #16</a>
	                </div>
	            </div>
              <div id="likers-container-382391" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="382391"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #16"></div>
  </section>
</div>
    <div class="postbit" id="382392" data-post-id="382392">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="garrison" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  garrison
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>You can definitely modify FDB and add a new role to parse WAL segments (this has been done before for streaming backups). Parsing the backup output from the DB itself is an interesting idea but I would expect there to be a lot of latency. I could be wrong.</p>
<p>There’s also the fact that mutations are spread semi-randomly onto TLogs due to FDB’s frankly unhinged replication policy. If you check the Hobbes repo I actually <em>just</em> wrote a new RFD about that because I’m finally moving to copysets. Gonna be some messy diffs today lol.</p>
<aside class="quote no-group" data-username="jstimps" data-post="17" data-topic="73767">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/jstimps/48/37213_2.png" class="avatar"> jstimps:</div>
<blockquote>
<p>Will Hobbes incrementalization be based off of a read version?</p>
</blockquote>
</aside>
<p>My <em>idea</em> is to allow a subscription to a key or range on a given Storage server. The Storage server already applies its mutations in perfect version order, so it can simply check the list of subscriptions as it goes.</p>
<p>It’s important that you can perform a read+subscribe without missing anything in between, and we can support that by performing the subscribe at the same <code>read_version</code> as the reads. At the time the subscription is opened the Storage server can read the multiversion store for that range and send logs for any keys that were modified <em>after</em> <code>read_version</code> immediately. I assume FDB watches must do something similar.</p>
<p>I don’t see any reason to send “from” versions. The primitive is “give me all changes for this range and <strong>do not miss any</strong>”. As long as you actually fulfill that promise, you can always reconstruct a valid view of the range.</p>
<p>There is one more edge case: you have to send nacks to the client when there are no mutations at a version. Otherwise you can’t maintain a view across shards because the frontier won’t advance.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="382392" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/support-for-realtime-server-side-updates-and-streams-like-liveview-and-phoenixsync/73767/18">Post #17</a>
	                </div>
	            </div>
              <div id="likers-container-382392" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="382392"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-last-post cat-last-post" title="Last post!"></div>
  </section>
</div>
</template></turbo-stream><turbo-stream action="replace" target="load-more-container"><template><div id="load-more-container" class="load-more-container">
    <span class="all-loaded">— All posts loaded —</span>
</div></template></turbo-stream>