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


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>You could have the sequencing of the command and the subcommand happen in the <em>calling</em> process:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">def SequencedOperations do
  use GenServer

  def run_simple_command(...etc...) do
    GenServer.call(...)
  end

  def run_complicated_command(...) do
    result1 = run_simple_command(...)

    run_other_simple_command(..., result1)
  end

  # handle_call etc
end
</code></pre>
<p>The client still sees a simple blocking API - <code>SequencedOperations.run_complicated_command()</code> and the GenServer is solely responsible for holding the state of the connection to the external binary.</p>
<hr>
<p>Something to think about regarding doing this asynchronously: what happens if another call comes in when a command is currently running? Does it go into a queue somehow? What’s the observable state of the GenServer “mid-command”?</p>
<p>At work we tried a similar asynchronous pattern in a complex state machine, and it was a mess - suddenly the async reply could arrive after the machine changed state, and the possible combinations got really unwieldy. In your case, consider simplifying the GenServer to selectively receive <em>just</em> the <code>{:stdout, _, _}</code> message:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">def handle_call({:do_thing, arg1}, from, state) do
  #  send command
  #  ...
  receive do
    {:stdout, _, reply_value} -&gt;
      # do something with reply_value and reply to from
    {:DOWN, _, _, _, reason} -&gt;
      # uh-oh the process went away
      # could also let this sit in the mailbox and have a top-level handler for it, with different timeout behavior
  after
    10000 -&gt;
      # timed out!
  end
</code></pre>
<p>To answer the previous questions, this approach:</p>
<ul>
<li>relies on the process mailbox to store calls that arrive while one is already in-flight</li>
<li>the state is only observable when a command is not in-flight</li>
</ul> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="181591" data-batch-url="/posts/batch_likers">
                        4
                      </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/design-problem-i-want-to-do-a-genserver-call-from-within-the-genserver/32783/12">Post #11</a>
	                </div>
	            </div>
              <div id="likers-container-181591" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="181591"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-most-liked cat-most-liked" title="One of the top 3 liked posts in this thread!"></div>
  </section>
</div>
    <div class="postbit" id="181597" data-post-id="181597">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="akoutmos" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/akoutmos/120/20230_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  akoutmos
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Author of Build a Weather Station with Elixir and Nerves</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>I have always stayed away from doing things like that personally as it may have unintended consequences..that and it feel dirty <a href="https://hexdocs.pm/elixir/GenServer.html#module-receiving-regular-messages" class="inline-onebox" rel="noopener nofollow ugc">GenServer — Elixir v1.20.2</a> <img src="https://forum.elixirforum.com/images/emoji/apple/stuck_out_tongue.png?v=15" title=":stuck_out_tongue:" class="emoji" alt=":stuck_out_tongue:" loading="lazy" width="20" height="20"></p>
<p>I’m not sure I follow 100% what you are trying to accomplish…so my suggestion may be way off the mark. But here goes.</p>
<p>Based off of your “ideal flow” chart, would it work if the caller makes a cast call to your GenServer along with the pid of itself and then immediately afterwards has a receive block waiting on a message back. In the mean time, the GenServer can perform a number of non-blocking operations in the background and once enough information has been aggregated, it can <code>send/2</code> back to the original caller’s pid (which needs to be stored in the GenServer state from the initial cast call).</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="181597" 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/design-problem-i-want-to-do-a-genserver-call-from-within-the-genserver/32783/13">Post #12</a>
	                </div>
	            </div>
              <div id="likers-container-181597" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="181597"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-most-liked cat-most-liked" title="One of the top 3 liked posts in this thread!"></div>
  </section>
</div>
    <div class="postbit" id="181617" data-post-id="181617">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="sasajuric" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/sasajuric/120/991_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  sasajuric
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Author of Elixir In Action</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Personally I’d have GenServer message protocol map 1:1 to the message protocol of the external program. In other words, if external program supports commands <code>foo</code> and <code>bar</code>, I’d only have <code>handle_call</code> for these two operations. If I wanted to do both, I’d call <code>foo</code> and then <code>bar</code> from the client process. This composition could still be wrapped in the interface function of the GenServer.</p>
<p>If the operation needs to be performed atomically, i.e. we don’t want any other client to invoke something untill both <code>foo</code> and <code>bar</code> have finished, my first option would be to support the composite <code>foo_bar</code> command in the external program. If that’s not possible (e.g. if I don’t have the control of the program code), then I’d solve this in the GenServer code by keeping track of the remaining commands which need to be invoked before returning the response with <code>GenServer.reply</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="181617" 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/design-problem-i-want-to-do-a-genserver-call-from-within-the-genserver/32783/14">Post #13</a>
	                </div>
	            </div>
              <div id="likers-container-181617" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="181617"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-most-liked cat-most-liked" title="One of the top 3 liked posts in this thread!"></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>