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


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="dimamik" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/dimamik/120/39846_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  dimamik
                    <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>Hey! I really appreciate the feedback!</p>
<aside class="quote no-group" data-username="Asd" data-post="11" data-topic="72553">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/a/c68b51/48.png" class="avatar"> Asd:</div>
<blockquote>
<ol>
<li>Wouldn’t it be faster (in terms of performance) and easier (in terms of maintenance) to use Registry? This way you won’t need to traverse the links tree (which is a pretty expensive thing to do) and you will have automatic cleanup of the data when the owner dies. Doing <code>Process.info(pid, :dictionary)</code> can be a very expensive operation, since it copies the whole dictionary (which can be quite big) into the current process and if the <code>pid</code> process is running, VM will block current process until the <code>pid</code> is interrupted, just in order to copy the dictionary.</li>
</ol>
</blockquote>
</aside>
<p>If I understand the idea correctly, we’d still need to traverse the process tree and do a Registry lookup for each process? <code>Process.info/2</code> is indeed expensive, but it’s only done once per process, so the cost should be neglectible, since <code>Vault</code> is cached locally afterwards, and subsequent lookups are cheap.</p>
<aside class="quote no-group" data-username="Asd" data-post="11" data-topic="72553">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/a/c68b51/48.png" class="avatar"> Asd:</div>
<blockquote>
<ol start="2">
<li>If you use Registry and remove local pdict cache, you can make this data mutable.</li>
</ol>
</blockquote>
</aside>
<p>The whole point was to make this data immutable, for ease of reasoning about it. Maybe it’s not an ideal assumption? I didn’t want to break FP purity patterns too much here.</p>
<aside class="quote no-group" data-username="Asd" data-post="11" data-topic="72553">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/a/c68b51/48.png" class="avatar"> Asd:</div>
<blockquote>
<ol start="3">
<li>It would be nice to have some function like <code>allow(parent_pid, other_pid)</code> which would allow <code>other_pid</code> process to access the state of the <code>parent_pid</code> process.</li>
</ol>
</blockquote>
</aside>
<p>I’m not sure if it’s needed, assuming we’re propagating the state to the bottom only. What will be a typical use-case for that?</p>
<aside class="quote no-group" data-username="Asd" data-post="11" data-topic="72553">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/a/c68b51/48.png" class="avatar"> Asd:</div>
<blockquote>
<ol start="4">
<li>Why “Vault”? I thought that Vault is a place where people put money so that no one can steal it. The name sounds more related to security, but that’s just how I feel it</li>
</ol>
</blockquote>
</aside>
<p>Easy to remember name, a little implying immutability “guarantees” of the data being stored in there.</p>
<aside class="quote no-group" data-username="Asd" data-post="11" data-topic="72553">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/a/c68b51/48.png" class="avatar"> Asd:</div>
<blockquote>
<ol start="5">
<li>It has bugs in it’s design. For example, process <code>a</code> is linked with processes <code>b</code> and <code>c</code>. Process <code>b</code> has key <code>b_key</code> set in it’s vault and process <code>c</code> has key <code>c_key</code> set in it’s vault. I won’t be able to access both keys in the first call. So, some unexpected link will produce a bug which would be very hard to catch</li>
</ol>
</blockquote>
</aside>
<p>This won’t happen, since Process C won’t be able to initialize its vault, because Process B already did. And we have a loose guarantee (excluding dynamic links and creations) for at most one vault per <a href="https://en.wikipedia.org/wiki/Component_(graph_theory)" rel="noopener nofollow ugc">connected components</a>. This might be too restrictive, since we’re not only traversing children, but all connections.<br>
Using <code>$ancestors</code> + <code>$callers</code> + <code>:erlang.process_info(self(), :parent)</code> as a list of associated processes should resolve both of these issues, since they’ll have a tree structure, and for a subtree - we’ll have a guarantee for a single vault.</p>
<blockquote>
<p>Overall, I wouldn’t use the library in it’s current state, but idea to have some storage which is accessible by direct children of the process is pretty good. If I were to solve this problem, I would use <code>$callers</code> and <code>$ancestors</code> with Registry entry.</p>
</blockquote>
<p>Can you elaborate more on why you see registry fit better here? I’m not seeing any clear benefits as for now, but I’m most likely missing something?</p>
<blockquote>
<p>And about GraphQL, I had a very similar problem and I just passed the user explicitly. Even if I have to pass it into 8 functions deep, I would just type 8 extra words, which is not a big deal, since explicit argument pays off in readability when compared to semi-global semi-mutable storage</p>
</blockquote>
<p>Actually, in relatively complex systems that are already built - this quickly became an issue when we needed to introduce audit logs with an actor. Places, where previously we didn’t have access to the user needed to have it, and there was no easy way to refactor all these functions to introduce another argument.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="373922" 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/vault-a-lightweight-process-scoped-global-data-storage-with-immutability-guarantees/72553/12">Post #11</a>
	                </div>
	            </div>
              <div id="likers-container-373922" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="373922"
                     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="373923" data-post-id="373923">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="dimamik" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/dimamik/120/39846_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  dimamik
                    <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>I think it’s actually somewhat different. <code>Vault</code>’s idea is to place some initialization guarantees, in addition to access guarantees.</p>
<p>We’ll have a vault per processes subtrees, and you won’t be able to override it from any of the children - by design. Accessing parent’s vault from a child process will indeed cache it in local process dict, this part is similar to what <code>ProcessTree</code> does at a first glance.</p>
<p>In the future, we might be able to provide granular caching controls, so that you tailor it to your specific needs.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="373923" 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/vault-a-lightweight-process-scoped-global-data-storage-with-immutability-guarantees/72553/13">Post #12</a>
	                </div>
	            </div>
              <div id="likers-container-373923" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="373923"
                     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="373928" data-post-id="373928">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Very cool! I really appreciate the Process-oriented architecture here, and looking forward to 0.2.1 using <code>$callers</code>.</p>
<p>This feels like an alternative take to <a href="https://hexdocs.pm/phoenix/scopes.html" rel="noopener nofollow ugc">Phoenix Scopes</a> – how do you think this could work with Scopes? I realize Vault is focused on secrets, but I figure there’s a lot of overlap in how it would be used, since scopes are also designed to alleviate property drilling.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="373928" 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/vault-a-lightweight-process-scoped-global-data-storage-with-immutability-guarantees/72553/14">Post #13</a>
	                </div>
	            </div>
              <div id="likers-container-373928" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="373928"
                     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="373931" data-post-id="373931">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="dimamik" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/dimamik/120/39846_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  dimamik
                    <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>Thanks!</p>
<blockquote>
<p>This feels like an alternative take to <a href="https://hexdocs.pm/phoenix/scopes.html" rel="noopener nofollow ugc">Phoenix Scopes</a> – how do you think this could work with Scopes?</p>
</blockquote>
<p>I think Phoenix Scopes are not solving the same problem <code>Vault</code> solves. Scopes standardize a way to initialize the context in a plug, but the problem of passing it down still persist.</p>
<p>I see two options of these two playing together:</p>
<ol>
<li>You still assign context to your connection/socket in the plug at the beginning of the request processing, but in addition to that, you’re also initializing a vault with a part of the context which is immutable and valid across the whole request processing.<br>
Then, down the flow, if you have access to conn/socket - you extract the context from there, but if you don’t - you use <code>Vault</code>.</li>
<li>Instead of putting the context in assigns, you only put it in <code>Vault</code>. Down the flow you’re always using <code>Vault</code>.</li>
</ol>
<p>I’m leaning over option 2 for simplicity reasons, but which one is better depends on a use-case.</p>
<blockquote>
<p>I realize Vault is focused on secrets, but I figure there’s a lot of overlap in how it would be used, since scopes are also designed to alleviate property drilling.</p>
</blockquote>
<p>Actually, Vault has nothing to do with secrets, and it’s probably a bad name for a library to manage state, buuuut, I like it still. I’ve chosen Vault to imply immutability guarantees that it gives to you. So it’s not just randomly putting things in Process dict, but you can only do this once per a subtree, and vault actually checks if any parent hadn’t initialized the vault before. This gives you more confidence in inferring where the value from the vault is actually coming from, which might pursue FP best practices.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="373931" 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/vault-a-lightweight-process-scoped-global-data-storage-with-immutability-guarantees/72553/15">Post #14</a>
	                </div>
	            </div>
              <div id="likers-container-373931" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="373931"
                     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="373937" data-post-id="373937">
  <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">
								<aside class="quote no-group" data-username="dimamik" data-post="12" data-topic="72553">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/dimamik/48/39846_2.png" class="avatar"> dimamik:</div>
<blockquote>
<p>This won’t happen</p>
</blockquote>
</aside>
<pre data-code-wrap="elixir"><code class="lang-elixir">iex(2)&gt; b = spawn(fn -&gt; Vault.init(b: 1); receive do x -&gt; x end end)
#PID&lt;0.239.0&gt;
iex(3)&gt; c = spawn(fn -&gt; Vault.init(c: 2); receive do x -&gt; x end end)
#PID&lt;0.240.0&gt;
iex(4)&gt; Process.link(b)
true
iex(5)&gt; Process.link(c)
true
iex(6)&gt; Vault.get :b
1
iex(7)&gt; Vault.get :c
nil
</code></pre>
<p>And the other way around</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">iex(2)&gt; b = spawn(fn -&gt; Vault.init(b: 1); receive do x -&gt; x end end)
#PID&lt;0.159.0&gt;
iex(3)&gt; c = spawn(fn -&gt; Vault.init(c: 2); receive do x -&gt; x end end)
#PID&lt;0.160.0&gt;
iex(4)&gt; Process.link(c)
true
iex(5)&gt; Process.link(b)
true
iex(6)&gt; Vault.get :c
2
iex(7)&gt; Vault.get :b
nil
</code></pre>
<hr>
<aside class="quote no-group" data-username="dimamik" data-post="12" data-topic="72553">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/dimamik/48/39846_2.png" class="avatar"> dimamik:</div>
<blockquote>
<p>we’d still need to traverse the process tree</p>
</blockquote>
</aside>
<p>Yeah, you’re right, this is a wrong argument for Registry, but this argument applies to my point about <code>$ancestors</code> and <code>$caller</code></p>
<aside class="quote no-group" data-username="dimamik" data-post="12" data-topic="72553">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/dimamik/48/39846_2.png" class="avatar"> dimamik:</div>
<blockquote>
<p>The whole point was to make this data immutable</p>
</blockquote>
</aside>
<p>Sure, but you already have the API to change the value, which only works for the current process. I only suggested to improve this situation. In the end of the day, any approach can be made immutable by removing the function to update the data <img src="https://forum.elixirforum.com/images/emoji/apple/grin.png?v=15" title=":grin:" class="emoji" alt=":grin:" loading="lazy" width="20" height="20"></p>
<aside class="quote no-group" data-username="dimamik" data-post="12" data-topic="72553">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/dimamik/48/39846_2.png" class="avatar"> dimamik:</div>
<blockquote>
<p>I’m not sure if it’s needed, assuming we’re propagating the state to the bottom only. What will be a typical use-case for that?</p>
</blockquote>
</aside>
<p>Tests, like common use case of Mox’s <code>allow</code>. Process pools. Or I use a library which just spawns a process without link and I want to share the state with it. Not all processes links form a tree, although that’s the best approach to do it imo.</p>
<aside class="quote no-group" data-username="dimamik" data-post="12" data-topic="72553">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/dimamik/48/39846_2.png" class="avatar"> dimamik:</div>
<blockquote>
<p>issue when we needed to introduce audit logs with an actor</p>
</blockquote>
</aside>
<p>I understand it now. Sounds like a use-case for <code>Logger.metadata</code></p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="373937" 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/vault-a-lightweight-process-scoped-global-data-storage-with-immutability-guarantees/72553/16">Post #15</a>
	                </div>
	            </div>
              <div id="likers-container-373937" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="373937"
                     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="373940" data-post-id="373940">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="dimamik" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/dimamik/120/39846_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  dimamik
                    <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="dimamik" data-post="12" data-topic="72553">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/dimamik/48/39846_2.png" class="avatar"> dimamik:</div>
<blockquote>
<p>(excluding dynamic links and creations)</p>
</blockquote>
</aside>
<p>Correct, in the example you’ve provided you’re linking the processes after initializing the vault, and because of that it’s not working. But I think not using links will eliminate this problem entirely.</p>
<blockquote>
<p>Yeah, you’re right, this is a wrong argument for Registry, but this argument applies to my point about <code>$ancestors</code> and <code>$caller</code></p>
</blockquote>
<p>Yep, will apply this, thanks!</p>
<blockquote>
<p>Sure, but you already have the API to change the value, which only works for the current process. I only suggested to improve this situation. In the end of the day, any approach can be made immutable by removing the function to update the data <img src="https://forum.elixirforum.com/images/emoji/apple/grin.png?v=15" title=":grin:" class="emoji" alt=":grin:" loading="lazy" width="20" height="20"></p>
</blockquote>
<p>It’s prefixed with <code>unsafe_*</code>, so it’s unsafe <img src="https://forum.elixirforum.com/images/emoji/apple/person_shrugging.png?v=15" title=":person_shrugging:" class="emoji" alt=":person_shrugging:" loading="lazy" width="20" height="20"> and I think we should be fine with not placing any expectations there? I’m open to any alternatives though</p>
<blockquote>
<p>Tests, like common use case of Mox’s <code>allow</code> . Process pools. Or I use a library which just spawns a process without link and I want to share the state with it. Not all processes links form a tree, although that’s the best approach to do it imo.</p>
</blockquote>
<p>I think using <code>$ancestors</code> + <code>$callers</code> + <code>:erlang.process_info(self(), :parent)</code> as a list of associated processes should resolve this issue and you’ll be able to initialize the state inside a setup block.</p>
<blockquote>
<p>I understand it now. Sounds like a use-case for <code>Logger.metadata</code></p>
</blockquote>
<p>Not really, I want to persist these audit logs in the database instead of flushing to some external system. Also, it’s not only applying to audit logging, there are a ton of places you need to refer to user (setting user-related columns in the db, which represent the actor of the action), verifying permissions closer to the context, and many, many more. Plus, it doesn’t need to be user, it can be a broader context where you put whatever you like. You just need to guarantee that it’s not changing across the request (or the changes of these entities do not impact the lifecycle of your process).</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="373940" 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/vault-a-lightweight-process-scoped-global-data-storage-with-immutability-guarantees/72553/17">Post #16</a>
	                </div>
	            </div>
              <div id="likers-container-373940" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="373940"
                     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="374056" data-post-id="374056">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="dimamik" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/dimamik/120/39846_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  dimamik
                    <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>I’ve just released <a href="https://github.com/dimamik/vault" rel="noopener nofollow ugc">Vault <code>v0.2.1</code></a>.</p>
<p>Thanks to <a class="mention" href="/u/asd" rel="nofollow">@Asd</a>, <a class="mention" href="/u/jswanner" rel="nofollow">@jswanner</a>, and other folks suggestions, we’re now relying on <code>ProcessTree</code> library to traverse process tree in an efficient and inclusive way. It relies on <code>Process.info(pid, :parent)</code> and fallbacks to processes <code>$ancestors</code> and <code>$callers</code> if OTP&lt;=24 or if parent process is dead, which is exactly what we need in this case.  Big kudos to <a href="https://github.com/jbsf2" rel="noopener nofollow ugc">JB Steadman</a>, the author of <code>ProcessTree</code>.</p>
<p>Since <code>ProcessTree</code> does all the heavy lifting for process traversal now, I was going back and forth on the need to have <code>Vault</code> as an abstraction layer above it in the first place. And I think it still has value in guaranteeing the immutability for the process subtree and defining a clean API on how to initialize and access this data.</p>
<p>My primary use-case was for propagating across a single process, so I definitely still see <em>some</em> value being added, but I would love to hear what you guys think!</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="374056" data-batch-url="/posts/batch_likers">
                        7
                      </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/vault-a-lightweight-process-scoped-global-data-storage-with-immutability-guarantees/72553/18">Post #17</a>
	                </div>
	            </div>
              <div id="likers-container-374056" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="374056"
                     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 #17"></div>
  </section>
</div>
    <div class="postbit" id="375802" data-post-id="375802">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>This seems very interesting – thanks for sharing!</p>
<p>One ‘pattern’ I use for solving what seem like very similar motivating problems is to create various ‘info types’. In C#, I’d create a class, but in Elixir often just a type suffices.</p>
<p>Info type values can be passed around in the ‘upstream portion’ of a call tree and they can be neatly handed off to the UI functions, e.g. rendering a page or a JSON response or outputting text to the REPL/console.</p>
<p>If some particular info types are commonly used, and/or you want something ‘stricter’, both structs and, e.g. Ecto embedded schemas, can be very handy too.</p>
<p>Basically, encapsulate the ‘process-call-tree-global-context’ into a type and pass values of that type around the call trees as needed or desired. ‘Context sharing’ is explicit, which is useful, but most callers can pass one argument instead of, e.g. seven, which is also nice for a few other reasons.</p>
<p>I could also imagine a system where your library would be super useful, e.g. I really WANT a single ‘global process call tree’ context and don’t want to have to pass it around explicitly.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="375802" 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/vault-a-lightweight-process-scoped-global-data-storage-with-immutability-guarantees/72553/19">Post #18</a>
	                </div>
	            </div>
              <div id="likers-container-375802" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="375802"
                     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 #18"></div>
  </section>
</div>
    <div class="postbit" id="375805" data-post-id="375805">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="dimamik" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/dimamik/120/39846_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  dimamik
                    <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>I like this idea too! The absolute benefit with using this kind of <code>args</code> (either “strict” structs or loose maps) is that we’re staying pure functional, without any implicit dependencies.<br>
The drawback, though, is that it quickly becomes too ambiguous. What to pass as a normal function argument, and what to put in <code>args</code>? You’ve mentioned that callers can omit passing all arguments, and pick arbitrary things they want. And I think this also becomes a problem, since now you need to know these hidden contracts.</p>
<p>So for me, I’d define the following gradation:</p>
<ol>
<li>For global, immutable context valid for every function call inside the process and its children - I’d use <code>Vault</code></li>
<li>For parameters that are valid for current execution branch, I’d use <code>params</code> function argument. I saw some efforts in creating validated schemas (like embedded schemas, but decoupled from Ecto), which I’d probably try first if I needed to have my params validated. <a href="https://github.com/phcurado/zoi" rel="noopener nofollow ugc">This library is called Zoi</a>, inspired by Zod.</li>
<li>And if it’s just for the sake of current function’s behavior - I’d use an old good function argument.</li>
</ol> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="375805" 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/vault-a-lightweight-process-scoped-global-data-storage-with-immutability-guarantees/72553/20">Post #19</a>
	                </div>
	            </div>
              <div id="likers-container-375805" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="375805"
                     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 #19"></div>
  </section>
</div>
    <div class="postbit" id="375881" data-post-id="375881">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>I’ve found that a lot of judgement of how to decide these kinds of things, for edge cases anyways, is very aesthetic – there’s almost always a taste or style that is very easily grokkable, for me and the rest of the team (if there is a team).</p>
<p>I’ve been using something very similar to your grades:</p>
<ol>
<li>I use Phoenix in a lot of my projects and sticking <em>some</em> info in the <code>Plug.Conn.t</code> values is perfectly fine, e.g. the current user (Ecto schema struct). That seems very much like what <code>Vault</code> is intended for, but without needing to explicitly thread the context value wherever it’s needed in a call tree.</li>
<li>I actually don’t like <code>params</code> arguments myself. I DO use <code>opts</code> liberally, and (try to) type every option explicitly too, and that’s very similar. What I was gesturing at is more like ‘a <code>Phoenix</code> assigns but more general’ and the reason that I mostly use these types at the ‘upper-stream’ of call trees is that’s a way to organize the state for the overall ‘project’ that the call tree is attempting. It’s also partly a way to ‘encourage’ good DB use, i.e. load ‘everything’ up front and then pass that, or pieces thereof, to the rest of the call tree. I work with lots of ‘legacy code’ and ‘just fetch it from the DB’ is all too common of a pattern, and all too commonly a source of performance issues. So think <code>ProcessPaymentInfo</code> instead of <code>params</code>, tho maybe I’m imagining more of a difference with what you meant. I’ve found tho that lots of functions near the top or in the middle of call trees can be very sensibly written to accept, e.g. <code>ProcessPaymentInfo</code>, or a collection of similar types. Typically almost all of the functions that accept, e.g. <code>ProcessPaymentInfo</code>, values would be in the same single module, or maybe a small set of modules (usually with a single ‘top-level facade’ module that all the other code is intended to use).</li>
<li>Yes, good ol’ function arguments are the generic ideal! The functions at the lower-stream of call trees should be cute little pure functions with a handful of regular ol’ arguments. All of the calls made by the <code>ProcessPaymentInfo</code> functions, to functions outside of their module(s), would pull out ‘sub values’ from the <code>ProcessPaymentInfo</code> value(s) and pass them as ‘regular’ function arguments.</li>
</ol>
<p>What are you using <code>Vault</code> for yourself? What are some other people using it for?</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="375881" 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/vault-a-lightweight-process-scoped-global-data-storage-with-immutability-guarantees/72553/21">Post #20</a>
	                </div>
	            </div>
              <div id="likers-container-375881" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="375881"
                     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 #20"></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/72553/load_more?page=3">Load more posts (3 remaining)</a>
</div></template></turbo-stream>