For the sake of history, here is a comment posted on Disqus
(discontinued on bounga.org) from Gin Lennon:
> Hi Nicolas, thanks a lot for sharing this blog post, I found it really
> interesting.
>
> I have a couple of comments and questions, I hope you don't mind if I
> post them here as a comment.
>
> 1. In the last iteration, the `Sequence.Server.start_link` receives
> the `stash_pid` as argument. How is injected? Is it passed by the
> `Supervisor`? And what is its purpose? It is not used anywhere as far
> I understood.
>
> 2. Always in the last iteration of the `Sequence.Server` the
> `terminate` callback calls the `save_link` function on the Agent, but
> this function is not implemented, did you mean to call the `update`
> one?
>
> 3. Regarding the `Sequence.Stash.update` function, I think there is an
> error in the implementation. The `Agent.update/3` requires a function
> as a second argument. Probably you meant something like:
> `Agent.update(__MODULE__, fn _ -> new_value end)`
>
> Thanks again and have a great day!
> Nico
My answer:
> Hi Nico.
>
> First of all thanks a lot for the read and moreover the comments. It really means a lot to me.
>
> About the comments and questions, you're in the right place. That's exactly why I add a comments system to my blog.
>
> So first, a note for my later self, I should never post a blog post again late at night...
>
> You spotted some big mistakes and I found some more by reading the post again. I already fixed everything so you know have a really working version without weird stuff.
>
> Now let me answer your questions:
>
> 1) So the variable called stash_id was an artefact.
>
> It does contains something since it is fed by the supervisor as you guessed but in our case it doesn't contain any useful value ({ Sequence.Server, nil }) since our server is meant to be stateless.
>
> We don't need any initial counter value nor the Stash pid since we're talking to it through its own module. On init through Sequence.Stash.get() to get the current value and also when the Server terminates (for any reason) using Sequence.Stash.update(current_number) to ensure we store the latest know value in the Stash.
>
> So yeah stash_pid was useless and wasn't even representing any kind of pid.
>
> 2) You caught another typo... I meant to use `update` yes.
>
> 3) Once again you're right! I had to wrap the new value in a function call
>
> I have addressed all the above issues and the post is up-to-date. I can't thank you enough for the time you spent on giving me these feedbacks.
>
> Have a nice day.
His reply:
> Hey Nicolas, thanks a lot for you exhaustive answer.
>
> I'll take advantage of your patience for another question.
>
> > We don't need any initial counter value nor the Stash pid since we're talking to it through its own module.
>
> Potentially, how would do you pass `Sequence.Stash` pid as argument to the `Sequence.Server.start_link` function?
>
> Thanks again :)
>
My next answer:
>> I'll take advantage of your patience for another question.
>
> No worries, I'd be more than happy to answer.
>
> As you know we are starting Sequence.Stash using the supervisor so we
> just donβt have access to the pid.
>
> The first solution that come to my mind is to give our process a name.
> That's what we did in this example:
>
> Agent.start_link(fn -> initial_value end, name: __MODULE__)
>
> so we're able to call it from anywhere:
>
> GenServer.call(Sequence.Stash, :next_number)
>
> In our case we're not using it from outside, the Stash module exposes a
> public API so it's enough to use it.
>
> The cool thing is you're able to do Process.whereis(Sequence.Stash)
> and you would get its PID back.
>
> But in my opinion, if your process / GenServer is supervised you
> should avoid relying on it pid to interact with it. If the supervision
> tree restarts your process (after a crash for instance) you'll be lost
> because the PID you know will be pointing to a dead process and you
> would have no way to know the new PID of the process.
>
> If you ever need to have multiple Stash maybe to have isolated counter
> for different context, I would use a dynamic process creation and
> still rely on name. Something like:
>
>
> iex> Sequence.Stash.start("first stash")
> iex> Sequence.Stash.start("second stash")
>
> iex> Sequence.Stash.get("first room")
> iex> Sequence.Stash.get("second room")
>
> The start function would make use of
> Supervisor.start_child(Sequence.Stash, [name]) so our dynamic process
> would be supervised as children of our stash module.
>
> There are other techniques available to handle more complex situations
> (https://hexdocs.pm/elixir/m... but I hope this answer gives you some
> clues. This subject deserves a whole blog post in fact.
>
> To sum up, I think you shouldn't try to handle PIDs by hand for
> supervised processes.
>
> Do this answer your question? Or am I completely off π
?
His last answer:
> Yup, it's perfect, thanks a lot for the detailed comment, really
> valuable! πβοΈ
--
Nicolas Cavigneaux
https://www.bounga.org
https://www.cavigneaux.net