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


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>I made a very simple LSM and I will try it out later today with Bedrock. Is there any bedrock benchmark or end-to-end test where I can check that Bedrock is working correctly with my storage?</p>
<p><a href="https://github.com/hissssst/nanolsm" class="onebox" target="_blank" rel="noopener nofollow ugc">https://github.com/hissssst/nanolsm</a></p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="373452" 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/bedrock-a-scaleable-distributed-key-value-database-with-better-than-acid-guarantees/72038/42">Post #41</a>
	                </div>
	            </div>
              <div id="likers-container-373452" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="373452"
                     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 #41"></div>
  </section>
</div>
    <div class="postbit" id="373635" data-post-id="373635">
  <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>Looks very nice! You should make a thread for it. There are questions I would ask but I don’t want to clog up this thread <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> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="373635" 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/bedrock-a-scaleable-distributed-key-value-database-with-better-than-acid-guarantees/72038/43">Post #42</a>
	                </div>
	            </div>
              <div id="likers-container-373635" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="373635"
                     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 #42"></div>
  </section>
</div>
    <div class="postbit" id="373678" data-post-id="373678">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="jallum" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/jallum/120/38850_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  jallum
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Take a look at storage.ex for the basic interface (all read-only) that the transaction builder expects, and you’ll want to look at the existing storage implementations for how to manage log-pulling. Storage servers in Bedrock (like fdb) only process transactions that have already been version-stamped and conflict checked, so all you need to worry about is applying those transactions and serving versioned reads.</p>
<p>I checked out the lib, and it’s a great start! I love building this kind of stuff!</p>
<p>At the moment, I don’t have any official benchmarking tools. With things starting to stabilize in 0.3, that’d be a good area to look into (along with automatic sharding, watches, better/simpler cluster config, documentation, 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="373678" 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/bedrock-a-scaleable-distributed-key-value-database-with-better-than-acid-guarantees/72038/44">Post #43</a>
	                </div>
	            </div>
              <div id="likers-container-373678" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="373678"
                     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 #43"></div>
  </section>
</div>
    <div class="postbit" id="373694" data-post-id="373694">
  <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>Thoughts on the API after reading the (brand) new guide:</p>
<p>I don’t like the <code>tx</code> being passed into the transaction <code>fn</code>. The API is not pure (<code>get()</code> and <code>put()</code> do not return a new transaction) so it feels weird to me. This is especially apparent in the composition example, where the <code>tx</code> is ignored and the called functions then get their own <code>tx</code> (from where?). Why is the explicit <code>tx</code> needed at all if the API is clearly not pure anyway?</p>
<p>You have <code>clear()</code> and <code>clear_range()</code> and then <code>get()</code> and <code>range()</code>. Why not <code>get_range()</code>?</p>
<p>I’m not sure how I feel about Subspaces. I know this comes from the FDB API but it seems like they exist solely to pack a tuple with a prefix. What purpose does a <code>Subspace</code> serve that is not already served by an arbitrary prefix tuple? I might be wrong about this one; I’m curious what <a class="mention" href="/u/jstimps" rel="nofollow">@jstimps</a> thinks here.</p>
<p>I think <code>Repo.transaction()</code> should mirror the new Ecto <code>Repo.transact()</code> API where the anonymous function returns <code>:ok/:error</code> tuples to be used for commit/rollback (of course here a rollback is a noop). It composes better, no need to repeat past mistakes there.</p>
<p>Have you given any thought to automatic retries for errors (e.g. conflicts)? One footgun is that some errors may not be retryable (network timeouts and recoveries). FDB had some work on automatic idempotency which was quite interesting. I personally plan to implement idempotency so that I can check linearizability after faults. (See also Tigerbeetle’s end-to-end idempotency, which is clever.)</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="373694" 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/bedrock-a-scaleable-distributed-key-value-database-with-better-than-acid-guarantees/72038/45">Post #44</a>
	                </div>
	            </div>
              <div id="likers-container-373694" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="373694"
                     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 #44"></div>
  </section>
</div>
    <div class="postbit" id="373719" data-post-id="373719">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="jallum" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/jallum/120/38850_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  jallum
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </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="45" data-topic="72038" data-full="true">
<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>Thoughts on the API after reading the (brand) new guide:</p>
</blockquote>
</aside>
<p>Feedback! Yay! <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"> Working against this demo/tutorial uncovered a lot of problems, both big and small. <strong>Big</strong> thanks to <a class="mention" href="/u/jstimps" rel="nofollow">@jstimps</a> – <a href="https://github.com/foundationdb-beam/erlfdb/blob/main/notebooks/tutorial-elixir.livemd" rel="noopener nofollow ugc">his version</a> for :erlfdb was the kick in the butt I needed.</p>
<aside class="quote no-group" data-username="garrison" data-post="45" data-topic="72038" data-full="true">
<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>I don’t like the <code>tx</code> being passed into the transaction <code>fn</code>. The API is not pure (<code>get()</code> and <code>put()</code> do not return a new transaction) so it feels weird to me. This is especially apparent in the composition example, where the <code>tx</code> is ignored and the called functions then get their own <code>tx</code> (from where?). Why is the explicit <code>tx</code> needed at all if the API is clearly not pure anyway?</p>
</blockquote>
</aside>
<p>This is a good point. Inside a transaction, there’s no real reason that it <em>has</em> to be passed around. It’s in the process dictionary… and that’s the way that transactions are automatically nested already… so I could easily remove the parameter from both the transaction function as well as the <code>get</code>, <code>put</code>, etc. functions. It’d certainly be less typing. I’ll give that a whirl and see what that looks/feels like.</p>
<aside class="quote no-group" data-username="garrison" data-post="45" data-topic="72038" data-full="true">
<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>You have <code>clear()</code> and <code>clear_range()</code> and then <code>get()</code> and <code>range()</code>. Why not <code>get_range()</code>?</p>
</blockquote>
</aside>
<p>Hahaha. Because I’ve been staring at it from 2" away, and it’s hard to see these things sometimes? <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"> <code>get_range</code> has a certain symmetry. That also sounds like a good tweak to make. Consider it done.</p>
<aside class="quote no-group" data-username="garrison" data-post="45" data-topic="72038" data-full="true">
<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>I’m not sure how I feel about Subspaces. I know this comes from the FDB API but it seems like they exist solely to pack a tuple with a prefix. What purpose does a <code>Subspace</code> serve that is not already served by an arbitrary prefix tuple? I might be wrong about this one; I’m curious what <a class="mention" href="/u/jstimps" rel="nofollow">@jstimps</a> thinks here.</p>
</blockquote>
</aside>
<p>Yeah. I straight copied the notion in my drive to duplicate the demo. Now that it <em>works</em>, it’s time to step back and see if some of these ideas can be made more “elixir-ish” I was thinking of reworking Subspace as a protocol, defimpl’d for binary()… it maybe could use a better name.</p>
<aside class="quote no-group" data-username="garrison" data-post="45" data-topic="72038" data-full="true">
<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>I think <code>Repo.transaction()</code> should mirror the new Ecto <code>Repo.transact()</code> API where the anonymous function returns <code>:ok/:error</code> tuples to be used for commit/rollback (of course here a rollback is a noop). It composes better, no need to repeat past mistakes there.</p>
</blockquote>
</aside>
<p>Up to 0.3, I was trying to do this very thing with transactions… but I came to think that trying to divine the will of the caller by picking apart the result is just kind of <em>dicey</em>. I can think of all sorts of reasons for wanting to return an error <em>without</em> rolling back. (For example: say i want to try to do something… but fail, but I still want to record the attempt.) The demo shows a raise for <code>"No remaining seats"</code>, but this could just as easily be a returned result.</p>
<p>Current behavior is to commit on any normal return without the result being interpreted in any way, and to only roll back on exception or explicit call to <code>Repo.rollback(reason)</code>. My thinking here is that if the user wants to rollback, they should just do that. I think this make a lot of sense in context, because a rollback or a no-change commit literally costs nothing, whereas a normal db, resources are tied up by the transaction and network round-trips are required to tear that down.</p>
<aside class="quote no-group" data-username="garrison" data-post="45" data-topic="72038" data-full="true">
<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>Have you given any thought to automatic retries for errors (e.g. conflicts)? One footgun is that some errors may not be retryable (network timeouts and recoveries). FDB had some work on automatic idempotency which was quite interesting. I personally plan to implement idempotency so that I can check linearizability after faults. (See also Tigerbeetle’s end-to-end idempotency, which is clever.)</p>
</blockquote>
</aside>
<p>Yes. This is already in place, for certain classes of “retryable” failures, notable examples being transient errors like: <code>version_too_new</code> or <code>unavailable</code> for reads and of course <code>aborted</code> (due to MVCC conflicts). There’s a scaled back-off (0, 2, 4, 8ms… up to 1s) with jitter. It was pretty much a requirement for the ‘concurrent’ portion of the notebook. It’s also how you can just “run” the notebook and the first <code>get(tx, "hello")</code> works without having to explicitly wait for the system to spin up.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="373719" 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/bedrock-a-scaleable-distributed-key-value-database-with-better-than-acid-guarantees/72038/46">Post #45</a>
	                </div>
	            </div>
              <div id="likers-container-373719" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="373719"
                     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 #45"></div>
  </section>
</div>
    <div class="postbit" id="373723" data-post-id="373723">
  <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">
								<aside class="quote no-group" data-username="jallum" data-post="46" data-topic="72038">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/jallum/48/38850_2.png" class="avatar"> jallum:</div>
<blockquote>
<p>I can think of all sorts of reasons for wanting to return an error <em>without</em> rolling back.</p>
</blockquote>
</aside>
<pre data-code-wrap="elixir"><code class="lang-elixir">Repo.transaction(fn -&gt;
  # ...
  {:ok, {:error, "No remaining seats."}}
end)
</code></pre>
<p>Read as “transaction succeeded, return value is an error”. This is fine, I think.</p>
<aside class="quote no-group" data-username="jallum" data-post="46" data-topic="72038">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/jallum/48/38850_2.png" class="avatar"> jallum:</div>
<blockquote>
<p>to only roll back on exception or explicit call to <code>Repo.rollback(reason)</code>. My thinking here is that if the user wants to rollback, they should just do that</p>
</blockquote>
</aside>
<p>This is how Ecto worked but we seem to have (mostly) reached community consensus that it was a mistake and that’s why there is a new <code>Repo.transact()</code> API. There are a couple of individuals on here that dissented, though, so maybe they’ll poke their heads in and disagree <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>
<aside class="quote no-group" data-username="jallum" data-post="46" data-topic="72038">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/jallum/48/38850_2.png" class="avatar"> jallum:</div>
<blockquote>
<p>because a rollback or a no-change commit literally costs nothing, whereas a normal db, resources are tied up by the transaction and network round-trips are required to tear that down</p>
</blockquote>
</aside>
<p>The explicit rollback is essentially using <code>try/catch</code> error-based control flow instead of <code>if/case/with</code> pattern matching control flow. The problem is that in Elixir we generally strongly favor the latter and rarely use the former, so building such a fundamental API (Ecto or Bedrock) on top of errors feels wrong (if we had algebraic effects maybe this would be different). If you use error tuples everywhere you can just use a <code>with</code> pipeline, whereas the rollback-based control flow resulted in the rather byzantine <code>Ecto.Multi</code> situation. <a href="https://tomkonidas.com/repo-transact/" rel="noopener nofollow ugc">This article has a nice visual example</a>.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="373723" 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/bedrock-a-scaleable-distributed-key-value-database-with-better-than-acid-guarantees/72038/47">Post #46</a>
	                </div>
	            </div>
              <div id="likers-container-373723" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="373723"
                     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 #46"></div>
  </section>
</div>
    <div class="postbit" id="373729" data-post-id="373729">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="dimitarvp" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/dimitarvp/120/38664_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  dimitarvp
                  </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="47" data-topic="72038">
<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>There are a couple of individuals on here that dissented, though, so maybe they’ll poke their heads in and disagree <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>
</blockquote>
</aside>
<p>Nope, I am quite fine, thank you.</p>
<p><img src="https://forum.elixirforum.com/images/emoji/apple/popcorn.png?v=15" title=":popcorn:" class="emoji only-emoji" alt=":popcorn:" loading="lazy" width="20" height="20"></p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="373729" 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/bedrock-a-scaleable-distributed-key-value-database-with-better-than-acid-guarantees/72038/48">Post #47</a>
	                </div>
	            </div>
              <div id="likers-container-373729" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="373729"
                     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 #47"></div>
  </section>
</div>
    <div class="postbit" id="373743" data-post-id="373743">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="jallum" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/jallum/120/38850_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  jallum
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group quote-modified" data-username="garrison" data-post="47" data-topic="72038" data-full="true">
<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>
<pre data-code-wrap="elixir"><code class="lang-elixir">  {:ok, {:error, "No remaining seats."}}
</code></pre>
<p>Read as “transaction succeeded, return value is an error”. This is fine, I think.</p>
</blockquote>
</aside>
<p>I suppose… if I squint a little. <img src="https://forum.elixirforum.com/images/emoji/apple/wink.png?v=15" title=":wink:" class="emoji" alt=":wink:" loading="lazy" width="20" height="20"></p>
<p>This is what you get when you use the old <code>Repo.transaction</code> with ecto and return an error… if you return <code>{:error, "No remaining seats."}</code> it wraps it with an <code>{:ok, ...}</code>. <code>Repo.transact</code> makes you do it yourself, in order to commit the transaction and return the error, just returning the error gets you a rollback.</p>
<aside class="quote no-group" data-username="garrison" data-post="47" data-topic="72038" data-full="true">
<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 how Ecto worked but we seem to have (mostly) reached community consensus that it was a mistake and that’s why there is a new <code>Repo.transact()</code> API.</p>
</blockquote>
</aside>
<p>…and how it <em>still</em> works with respect to <code>rollback/1</code>.  From within a <code>transact</code> the returned value for <code>Repo.rollback(:reason)</code> is <code>{:error, :reason}</code>.  The old <code>transaction</code> behaved the same way with respect to <code>rollback/1</code>, but <em>annoyingly wrapped</em> whatever you returned from your transaction function with an <code>:ok</code> tuple, so return <code>your_result</code> and you get  <code>{:ok, your_result}</code>… (return <code>:ok</code> and you get <code>{:ok, :ok}</code>).</p>
<p>The fact that the new <code>transact</code> function <em>just leaves your result alone</em> is kind of a cause for joy, though it seems that there’s no (documented) way to just return <code>:ok</code> to commit without a whole tuple.</p>
<p>Ultimately, I don’t feel super strongly one way or the other and I’m going to lean heavily in the direction of established patterns. It’s really only a couple of lines of code to do things the way <code>transact</code> does. <s>I’ll probably have</s> I added a commit to <a href="https://github.com/jallum/bedrock/pull/51" rel="noopener nofollow ugc">this PR</a>.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="373743" data-batch-url="/posts/batch_likers">
                        2
                      </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/bedrock-a-scaleable-distributed-key-value-database-with-better-than-acid-guarantees/72038/49">Post #48</a>
	                </div>
	            </div>
              <div id="likers-container-373743" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="373743"
                     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 #48"></div>
  </section>
</div>
    <div class="postbit" id="373744" data-post-id="373744">
  <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="45" data-topic="72038">
<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>I don’t like the <code>tx</code> being passed into the transaction <code>fn</code>. The API is not pure (<code>get()</code> and <code>put()</code> do not return a new transaction) so it feels weird to me. This is especially apparent in the composition example, where the <code>tx</code> is ignored and the called functions then get their own <code>tx</code> (from where?). Why is the explicit <code>tx</code> needed at all if the API is clearly not pure anyway?</p>
</blockquote>
</aside>
<p>This is a good point, but instead of removing the <code>tx</code> I do wonder how it would feel to lean in to it, and make the RYW tx immutable data. If it can be done with still an ergonomic API, you could get one of the benefits of nested transactions, the ability to abandon a subset of operations in the tx, without the IMO confusing semantics that would come from true nesting. The ergonomics might not be there though, since the <code>get</code> would have to return <code>{value, tx}</code> or similar. I could understand going either way. Immutability has served us well though.</p>
<aside class="quote no-group" data-username="garrison" data-post="45" data-topic="72038">
<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>What purpose does a <code>Subspace</code> serve that is not already served by an arbitrary prefix tuple?</p>
</blockquote>
</aside>
<p>I think it’s an important API concept to the end user; it leads them down the path of understanding the power of the ordered keyset. And each use of a subspace is equivalent to an index that doesn’t have to be written. Although, I admit I’ve only used FDB subspace in production code via the Directory layer.</p>
<aside class="quote no-group" data-username="garrison" data-post="45" data-topic="72038">
<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>the new Ecto <code>Repo.transact()</code> API</p>
</blockquote>
</aside>
<p>In a new system like Bedrock, I agree that <code>transact</code> is the way. However, <code>{:ok, {:error, _}}</code> as an idiomatic pattern is not ideal.</p>
<p>For the record though, I went a different third way with EctoFDB, since :erlfdb already had an established pattern embracing throws. Instead of transaction or transact, the EctoFDB adapter creates a new <code>Repo.transactional</code> to match <code>:erlfdb.transactional</code>. I did this because I didn’t want EctoFDB to be subjected to the future deprecation and removal of <code>Repo.transaction</code>.</p>
<p>In practice, the transactional throws have served me quite well in production code. But perhaps this is my <a href="https://en.wikipedia.org/wiki/Judgement_of_Solomon" rel="noopener nofollow ugc">Judgement of Solomon</a> moment <img src="https://forum.elixirforum.com/images/emoji/apple/grimacing.png?v=15" title=":grimacing:" class="emoji" alt=":grimacing:" loading="lazy" width="20" height="20">.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="373744" 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/bedrock-a-scaleable-distributed-key-value-database-with-better-than-acid-guarantees/72038/50">Post #49</a>
	                </div>
	            </div>
              <div id="likers-container-373744" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="373744"
                     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 #49"></div>
  </section>
</div>
    <div class="postbit" id="373745" data-post-id="373745">
  <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="jallum" data-post="46" data-topic="72038">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/jallum/48/38850_2.png" class="avatar"> jallum:</div>
<blockquote>
<p><strong>Big</strong> thanks to <a class="mention" href="/u/jstimps" rel="nofollow">@jstimps</a></p>
</blockquote>
</aside>
<p>Cheers! Always happy to be involved in exciting projects!</p>
<p>Some minor feedback on the API. As a new user, I would be confused by using the <code>Key</code> module to encode a value. An excerpt from the tutorial:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">      key = Subspace.pack(course, class)
      value = Key.pack(@total_seats_available)
      Repo.put(tx, key, value)
</code></pre> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="373745" 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/bedrock-a-scaleable-distributed-key-value-database-with-better-than-acid-guarantees/72038/51">Post #50</a>
	                </div>
	            </div>
              <div id="likers-container-373745" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="373745"
                     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 #50"></div>
  </section>
</div>
</template></turbo-stream><turbo-stream action="replace" target="load-more-container"><template><div id="load-more-container" class="load-more-container">
    <a class="load-more-button" data-turbo-stream="true" href="/topics/72038/load_more?page=6">Load more posts (17 remaining)</a>
</div></template></turbo-stream>