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


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group quote-modified" data-username="tomekowal" data-post="11" data-topic="22119">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/tomekowal/48/2847_2.png" class="avatar"> tomekowal:</div>
<blockquote>
<p>You’ve assumed that HTTP calls are potentially crashing, but most HTTP libraries don’t throw exceptions but return <code>{:error, reason}</code> . It might be OK to keep the state and work in one process as <span class="mention">@idiot</span> suggested.</p>
</blockquote>
</aside>
<p>Just to be clear, I suggested still crashing the http requests, but do it in a supervised non-linked <a href="https://hexdocs.pm/elixir/Task.Supervisor.html#async_nolink/3" rel="noopener nofollow ugc">task</a> (or <a href="https://hexdocs.pm/elixir/Task.Supervisor.html#async_nolink/3" rel="noopener nofollow ugc">stream</a> if there are multiple requests), so that the calling process that keeps the state doesn’t get linked and crash with the failing http request, but we still get the nice error message from the exception with the stacktrace.</p>
<pre data-code-wrap="elixir"><code class="lang-elixir"># adapted the demo snippet from the docs for Task.Supervisor

  # etc ...
  def handle_info({:http_get, url} %{tasks: tasks} = state) do
    task =
      Task.Supervisor.async_nolink(MyApp.TaskSupervisor, fn -&gt;
        HTTPoison.get!(url) # &lt;-- still using the `!` version to crash when appropriate
      end)

    {:reply, :ok, %{state | tasks: Map.put(tasks, task.ref, %{task: task, url: url})}}
  end

  # The task completed successfully
  def handle_info({ref, %HTTPoison.Response{body: _body}}, %{tasks: %{ref =&gt; %{url: url}} = tasks} = state) do
    # do something with the http reply
    Process.demonitor(ref, [:flush])
    {:noreply, %{state | tasks: Map.delete(tasks, ref)}}
  end

  def handle_info({ref, _}, state) do
    # "response" from a "stray" task? Not sure when this can happen
    {:noreply, state}
  end

  # The task failed
  def handle_info({:DOWN, ref, :process, _pid, _reason}, %{tasks: %{ref =&gt; %{url: url}} = tasks} = state) do
    # Log and possibly restart the task... (we still have the url for the request)
    {:noreply, %{state | tasks: Map.delete(tasks, ref)}}
  end

  def handle_info({:DOWN, _ref, :process, _pid, _reason}, state) do
    # I sometimes get the DOWN message even though the process has been demonitored, probably some internal race condition
    {:noreply, state}
  end

  # etc ...
</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="127498" 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/supervision-strategy-for-a-stateful-web-client/22119/12">Post #11</a>
	                </div>
	            </div>
              <div id="likers-container-127498" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="127498"
                     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="127504" data-post-id="127504">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="chgeuer" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/chgeuer/120/10510_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  chgeuer
                    <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 <a class="mention" href="/u/tomekowal" rel="nofollow">@tomekowal</a> for the insights. Totally get the b) topic on <code>Worker.start_link/1</code> running in the context of the <code>WorkerSupervisor</code>, and therefore somehow bringing the <code>self()</code> call ‘down’.</p>
<p>Regarding your a) suggestion to use a <code>:rest_for_one</code> strategy, and that the worker can’t exist without the agent: In principle I understand that the worker needs an agent to store it’s state. However, the implementation currently has an interesting quirk: The worker doesn’t store the <code>Agent</code>’s pid, but always asks the parent <code>Supervisor</code> for the agent’s pid. In a situation where the worker is humming along, it has an up-to-date copy of the current state <em>in the worker</em>. If the Agent now crashes, the Supervisor re-starts a fresh (empty) agent. In the next ‘save’ operation (from the worker to the agent), the latest state get’s ‘replicated’ from the worker to the agent. So by keeping the worker running when the agent dies, I still have a copy of the current state.</p>
<p>Does that make sense?</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="127504" 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/supervision-strategy-for-a-stateful-web-client/22119/13">Post #12</a>
	                </div>
	            </div>
              <div id="likers-container-127504" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="127504"
                     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="127505" data-post-id="127505">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="chgeuer" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/chgeuer/120/10510_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  chgeuer
                    <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 (!) <a class="mention" href="/u/idi527" rel="nofollow">@idi527</a> for the feedback. I need to look deeper into the behavior of my HTTP client (Tesla with :ibrowse). In my current <a href="https://github.com/chgeuer/ex_microsoft_azure_storage/blob/master/lib/microsoft/azure/storage/rest_client.ex#L6-L27" rel="noopener nofollow ugc">Azure storage SDK code</a>, I’ve integrated support for using Fiddler (Windows HTTP proxy) for debugging my calls. When Fiddler isn’t listing on 127.0.0.1:8080, the HTTP calls brought the process down, no friendly tuples and stuff <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"> . Potentially I’m doing something wrong over there…</p>
<p>This <a href="https://gist.github.com/chgeuer/275a16ee17d2a13f1442bae4bd77269a" rel="noopener nofollow ugc">prototype</a> here is also for me to learn how to properly leverage the OTP pieces properly, sorry if I mix too many things together.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="127505" 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/supervision-strategy-for-a-stateful-web-client/22119/14">Post #13</a>
	                </div>
	            </div>
              <div id="likers-container-127505" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="127505"
                     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="127532" data-post-id="127532">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<blockquote>
<p>This <a href="https://gist.github.com/chgeuer/275a16ee17d2a13f1442bae4bd77269a" rel="noopener nofollow ugc">prototype</a> here is also for me to learn how to properly leverage the OTP pieces properly, sorry if I mix too many things together.</p>
</blockquote>
<p>I have a <a href="https://github.com/syfgkjasdkn/exits/blob/master/test/exits_test.exs" rel="noopener nofollow ugc">demo repo</a>  with different tasks crashing without bringing down the caller. Hope it might help.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="127532" 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/supervision-strategy-for-a-stateful-web-client/22119/15">Post #14</a>
	                </div>
	            </div>
              <div id="likers-container-127532" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="127532"
                     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="127554" data-post-id="127554">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group quote-modified" data-username="chgeuer" data-post="13" data-topic="22119">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/chgeuer/48/10510_2.png" class="avatar"> chgeuer:</div>
<blockquote>
<p>The worker doesn’t store the <code>Agent</code> 's pid, but always asks the parent <code>Supervisor</code> for the agent’s pid. In a situation where the worker is humming along, it has an up-to-date copy of the current state <em>in the worker</em> . If the Agent now crashes, the Supervisor re-starts a fresh (empty) agent. In the next ‘save’ operation (from the worker to the agent), the latest state get’s ‘replicated’ from the worker to the agent. So by keeping the worker running when the agent dies, I still have a copy of the current state.</p>
<p>Does that make sense?</p>
</blockquote>
</aside>
<p>I understand what you’re writing, but I don’t think it makes sense <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"> The worker can fail because it has some work to do, that is complex and can crash. Why would Agent with state crash? If the only functions are <code>set_state</code> and <code>get_state</code>, it doesn’t do any computations. The only interactions it has, are with the Worker. If the Agent crashed, that means that Worker did something terrible to it and potentially has a bad state. You don’t want to copy that state back. You’d instead restart both.</p>
<p>I guess the idea of guarding state in both processes comes from a wrong mode of thinking: “what happens if one of the processes randomly crashes?”. Processes don’t crash randomly. They crash when they are either doing complex work that can produce an unexpected/unhandled result or use external resources like files or network.</p>
<p>The second rule of thumb is that “computation is cheap, but data is sacred”. It is usually better to wipe out potentially broken state than to let the error propagate. Your state process might guard itself against the wrong state by using an interface that crashes the worker process. E.g.</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">def set_state(pid, %{counter: counter, interval: interval} = state) when is_integer(counter) and is_integer(interval) do
  Agent.update(pid, fn _ -&gt; state end)
end
</code></pre>
<p>You can do other checks before calling Agent, and it will potentially crash worker guarding the data.</p>
<p>I believe a lot of fault tolerance in the BEAM stems from not letting the error propagate. You would continue with the initial state if something went wrong.</p>
<p>Let’s look at those two solutions in the light of the use case from the first post: authentication.<br>
In the solution when crashing the Agent starts with a clean state the device will need to reauthenticate. It is an inconvenience but not a big deal.<br>
In the solution that copies state back and forth, the crash could happen because the worker was poorly implemented and did something strange to the state. It then propagates that error back to the agent, and you can potentially authenticate someone else or let anyone connect or end up in a dangerous security breach.</p>
<p>To sum up: I don’t think it is a good idea to get the state back from the worker when an agent crashes.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="127554" 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/supervision-strategy-for-a-stateful-web-client/22119/16">Post #15</a>
	                </div>
	            </div>
              <div id="likers-container-127554" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="127554"
                     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="127587" data-post-id="127587">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="tomekowal" data-post="16" data-topic="22119">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/tomekowal/48/2847_2.png" class="avatar"> tomekowal:</div>
<blockquote>
<p>Why would Agent with state crash? If the only functions are <code>set_state</code> and <code>get_state</code> , it doesn’t do any computations.</p>
</blockquote>
</aside>
<p>Ultimately that is my beef with Agents - their state is entirely at the mercy of the functions that are sent to them by <strong>other</strong> processes. At least with a <code>GenServer</code> it can be easily enforced that interactions with the state <em>are simple</em>.</p>
<hr>
<p>Aside: In <em>Programming Elixir 1.3 - Chapter 18: OTP Supervisors</em></p>
<p>This tree structure was used:</p>
<pre><code class="lang-plaintext">Supervisor
|__ Stash
|__ SubSupervisor
    |__ Server
</code></pre>
<p><a href="https://media.pragprog.com/titles/elixir13/code/otp-supervisor/2/sequence/lib/sequence.ex" class="onebox" target="_blank" rel="noopener nofollow ugc">https://media.pragprog.com/titles/elixir13/code/otp-supervisor/2/sequence/lib/sequence.ex</a><br>
<a href="https://media.pragprog.com/titles/elixir13/code/otp-supervisor/2/sequence/lib/sequence/supervisor.ex" class="onebox" target="_blank" rel="noopener nofollow ugc">https://media.pragprog.com/titles/elixir13/code/otp-supervisor/2/sequence/lib/sequence/supervisor.ex</a><br>
<a href="https://media.pragprog.com/titles/elixir13/code/otp-supervisor/2/sequence/lib/sequence/stash.ex" class="onebox" target="_blank" rel="noopener nofollow ugc">https://media.pragprog.com/titles/elixir13/code/otp-supervisor/2/sequence/lib/sequence/stash.ex</a><br>
<a href="https://media.pragprog.com/titles/elixir13/code/otp-supervisor/2/sequence/lib/sequence/sub_supervisor.ex" class="onebox" target="_blank" rel="noopener nofollow ugc">https://media.pragprog.com/titles/elixir13/code/otp-supervisor/2/sequence/lib/sequence/sub_supervisor.ex</a><br>
<a href="https://media.pragprog.com/titles/elixir13/code/otp-supervisor/2/sequence/lib/sequence/server.ex" class="onebox" target="_blank" rel="noopener nofollow ugc">https://media.pragprog.com/titles/elixir13/code/otp-supervisor/2/sequence/lib/sequence/server.ex</a></p>
<p>In <em>Programming Elixir 1.6</em> that was replaced with a <code>:rest_for_one</code> strategy on</p>
<pre><code class="lang-plaintext">Supervisor
|__ Stash
|__ Server
</code></pre>
<p><a href="https://media.pragprog.com/titles/elixir16/code/otp-supervisor/2/sequence/lib/sequence/application.ex" class="onebox" target="_blank" rel="noopener nofollow ugc">https://media.pragprog.com/titles/elixir16/code/otp-supervisor/2/sequence/lib/sequence/application.ex</a></p>
<p>The primary issue with the <code>server</code> code was that the stash was only updated in the terminate callback which <a href="https://forum.elixirforum.com/t/supervisor-terminate-child-doesnt-call-terminate-callback-on-child/12949/3" rel="nofollow">won’t always run</a>. The backing store needs to be updated whenever we are certain that the new state is consistent.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="127587" data-batch-url="/posts/batch_likers">
                        3
                      </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/supervision-strategy-for-a-stateful-web-client/22119/17">Post #16</a>
	                </div>
	            </div>
              <div id="likers-container-127587" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="127587"
                     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="127596" data-post-id="127596">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="chgeuer" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/chgeuer/120/10510_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  chgeuer
                    <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="tomekowal" data-post="16" data-topic="22119">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/tomekowal/48/2847_2.png" class="avatar"> tomekowal:</div>
<blockquote>
<p>I guess the idea of guarding state in both processes comes from a wrong mode of thinking: “what happens if one of the processes randomly crashes?”. Processes don’t crash randomly.</p>
</blockquote>
</aside>
<p>Great feedback, that was what I was looking for. I must admit I’m still wrapping my head around the intricacies of how actor-based systems should behave. When I read it in a book, it all makes sense, but the books always describe the happy path. The thorough feedback here in the Elixir Forum is awesome.</p>
<p>Thanks, everybody!</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="127596" 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/supervision-strategy-for-a-stateful-web-client/22119/18">Post #17</a>
	                </div>
	            </div>
              <div id="likers-container-127596" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="127596"
                     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="127606" data-post-id="127606">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>I <em>really</em> think that you want to use names here instead of always going through the supervisor. This removes a bottleneck from your system and makes it easier to reason about crashes. I also want to add some nuance to what <a class="mention" href="/u/tomekowal" rel="nofollow">@tomekowal</a> is saying about state.</p>
<p>Processes absolutely can crash for no reason. This is typically do to a supervisor being restarted due to an unrelated crash. For instance your worker and agent may be working fine but their supervisor is managed by a supervisor with an <code>all_for_one</code> strategy. If one of your supervisors siblings crashes then your worker and agent will be restarted as well. This is pretty rare but is worth keeping in mind.</p>
<p>But <a class="mention" href="/u/tomekowal" rel="nofollow">@tomekowal</a>’s main point is correct. Most of the time a process will crash because it ends up in a bad state. When that happens it’s better to just allow the process to crash and come back in a good state.</p>
<p>The main issue with the way you’ve built your system currently is that the worker is responsible for pushing state into the agent. What that means is that if your worker state is bad than you’ll push bad state into the agent, and the agent will crash. This will continue happening repeatedly because the bad state is never being cleaned up. We aren’t allowing the agent to come back up in a known good state. These kinds of bugs crop up all the time especially when people intermingle persistence with their process state. The bad state is persisted somewhere, process crashes, process restarts and loads data into memory, next message it crashes again, etc.</p>
<p>What I try to do is to isolate my state to a single process as much as possible. I then send commands to that process and allow that process to update its own internal state. If something gets into a bad state the crash will be isolated and I can restart in a good state.</p>
<p>Here’s how I would re-write what you have so far: <a href="https://gist.github.com/keathley/36e536e7b55d7444752bd29fb8d25d4d" class="inline-onebox" rel="noopener nofollow ugc">stateful_server example · GitHub</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="127606" data-batch-url="/posts/batch_likers">
                        5
                      </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/supervision-strategy-for-a-stateful-web-client/22119/19">Post #18</a>
	                </div>
	            </div>
              <div id="likers-container-127606" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="127606"
                     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="127647" data-post-id="127647">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="axelson" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/axelson/120/26351_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  axelson
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Scenic Core Team</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>I’d just like to mention a good <a href="https://jlouisramblings.blogspot.com/2010/11/on-erlang-state-and-crashes.html" rel="nofollow">blog post</a> on state isolation. It introduces the idea of an “error kernel”:</p>
<blockquote>
<p>Erlang programs have a concept called the  <em>error kernel</em> . The kernel is the part of the program which  <em>must</em>  be correct for its correct operation. Good Erlang design begins with identifying the error kernel of the system: What part  <em>must</em>  not fail or it will bring down the whole system? Once you have the kernel identified, you seek to make it minimal. Whenever the kernel is about to do an operation which is dangerous and might crash, you “outsource” that computation to another process, a dumb slave worker. If he crashes and is killed, nothing really bad has happened - since the kernel keeps going.</p>
</blockquote> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="127647" data-batch-url="/posts/batch_likers">
                        5
                      </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/supervision-strategy-for-a-stateful-web-client/22119/20">Post #19</a>
	                </div>
	            </div>
              <div id="likers-container-127647" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="127647"
                     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>