<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Rob Ashton's blog]]></title><description><![CDATA[Software development dumping ground]]></description><link>http://codeofrob.com</link><image><url>http://codeofrob.com/img/cover.jpg</url><title>Rob Ashton&apos;s blog</title><link>http://codeofrob.com</link></image><generator>RSS for Node</generator><lastBuildDate>Mon, 17 Aug 2026 16:10:36 GMT</lastBuildDate><atom:link href="http://feeds.feedburner.com/robashton" rel="self" type="application/rss+xml"/><author><![CDATA[Rob Ashton]]></author><item><title><![CDATA[The launching of a product, or where I've been for the last few years]]></title><description><![CDATA[<p>Rejoice!</p>
<p>I have somehow managed to revive my blog without having to write any code, change any CSS or do any busy work at all thanks to the miracle of Github pages and the fact that my website was always just a pile of static pages generated by some terribly written JS that hasn&#39;t changed in nearly a decade - who says code rots?</p>
<h2 id="where-the-hell-have-i-been">Where the hell have I been?</h2>
<p>I&#39;m honestly quite surprised at how many people have reached out over the last few years to ask this question - I can either consider this a testament to how much impact I&#39;ve made over those years, or simply because I&#39;ve always been a noisy person and any silence from over in my corner is deafening.</p>
<p>The answer is that it turns out that when I&#39;m actively engaged in writing software that people are actually going to use and I&#39;m being fulfilled by that task, that I really don&#39;t feel the urge to try and talk about software development with people. The fact is I&#39;ve spent nearly a decade now helping our customers with their bespoke media workflows and that job has been all the software development chat that I really need in my life.</p>
<p>The last few years we&#39;ve been heads down productising (is this a word?) the knowledge and code we&#39;ve built up over the years so that our potential customers (who often already have software teams of their own) can start to build out some fairly advanced capabilities without having to become media technology companies themselves and without them having to teach us everything about their business.</p>
<h2 id="those-were-definitely-some-words">Those were definitely some words</h2>
<p>There are a lot of off the shelf media technology solutions out there for performing a wide variety of tasks, and they are typically (because of the complexity involved) fire and forget &quot;set it up and forget about it&quot; systems. Media is messy and there are a lot of media products out there who are responsible for taking content from a variety of sources, packaging up that content and then distributing that content to end users so it can be consumed. </p>
<p>A starter solution for fledgling companies who reach the limits of these black boxes might be to write some scripts to glue these tools together (often using ffmpeg), and while this might get you so far, sooner or later this approach runs out of steam and somebody needs to write some actual code.</p>
<p>At this point you&#39;ve got two options - you can perform this task in-house and take on the complexities that this involves (hint: this is a dangerous path!), or you can take on the services of one of the many systems integrators out there and get them to do this for you with all the in-house expertise they have, exchanging the cost of technical ownership for a simple license or service fee. </p>
<p>We (<a href="https://www.id3as.com/">id3as</a>) have always taken on the more challenging of these jobs, the jobs that others would maybe consider to be technically expensive and the jobs that have maybe even already been attempted by others to little success. We have been unafraid to use new (and old) technologies to solve problems and because of our experience and existing codebase we often find that the bulk of the effort is in the understanding of the business requirements of our customers rather than the technical challenges presented by the media itself. 
And isn&#39;t that the rub? The people with the business knowledge that know what they want are the best people to be building software around their own requirements, but the people who know how to deal with the complexities of fairly involved media workflows are external to that. For our own sins this often means we end up with customer logic inside our shared code out of necessity because everybody has a different idea about how fairly basic operations should take place (quality of service controls, pid mapping, source failover, etc).</p>
<p>We have repeatedly for our own benefit attempted to separate these concerns in order to better be able to respond to the needs of our customers without burying ourselves in complicated configuration and while we have always managed to get to somewhere better than we were, we haven&#39;t (until recently) come up with a platform that really delivers this. </p>
<h2 id="enter-norsk">Enter Norsk</h2>
<img width="200px" style="float: left;" src="/images/trinorsk.png" alt="The trinorsk Mascot (a blue triceratops wearing a viking helmet with three horns.." title="Trinorsk Mascot" />


<p>I&#39;m not entirely sure how it happened - we were taking our existing stack and upgrading it to help us maintain our own velocity (that&#39;s when we started heavily using Purescript for those that have been paying attention!), and in the process of doing this we started to see the shape of a product that we could use to keep our customer&#39;s business logic and the complex media orchestration separate and wholeheartedly pursued it.</p>
<p>Not only did it make sense, but it started to look as though we might be able to let other people use this platform to build their own complex workflows and that was incredibly exciting to us - obviously we did the only sensible thing at this point and committed to it - using it to do a few jobs for our existing customers as well as sharing it with a few trusted partners to see what they made of it. </p>
<p>The result of all this is that we&#39;re now shipping a product comprised of some incredibly clever technology written in a language that helps us avoid failure (Purescript), built on a platform that makes its name out of handling failure when it happens (Erlang) and allowing business logic to be written in a universally understood language (Javascript/Typescript) whilst taking care of the nitty gritty details of workflow management and ensuring automatically that customers have all the introspection, logs, metrics, and debugging tools that companies have come to expect in modern distributed systems. As we always have done, we integrate directly with the codecs we use and implement most protocols ourself so we have the power to work with the &quot;nuances&quot; of other implementations and as a result of this we have a flexibility to respond to challenges that is hard for a lot of people to fathom. </p>
<h2 id="in-a-nutshell">In a nutshell</h2>
<p>You spin up a Norsk server, connect to it over the Typescript SDK and say </p>
<ul>
<li>&quot;I want these ingest nodes to exist&quot;,</li>
<li>&quot;I want these transforms and control nodes to exist&quot;</li>
<li>&quot;I want these output nodes to exist&quot;</li>
<li>&quot;These are the actions I want you take as data flows over these nodes&quot;<ul>
<li>Subscribe nodes to the nodes</li>
<li>Update internal dashboards/etc</li>
<li>Update the configuration of running nodes on the fly </li>
</ul>
</li>
</ul>
<p>That last section is probably the most interesting - instead of fire and forget configuration, every decision that Norsk makes about media flows through the client application - a new stream appears and the client application is asked &quot;where do you want this to go?&quot;, metadata changes and the client application is asked &quot;does this change what you want?&quot;, various control nodes can flow frame by frame information to the client and allow it to respond in realtime to events in the media and update config across any node without causing any service interruption.</p>
<p>Norsk takes care of the media technology problems such as orchestration, codec knowledge, protocols and conversions and the client application gets to take care of decisioning and control - this is somwhat revolutionary. I several times over a recent conference where we launched the product tongue-in-cheek simplified this to &quot;it&#39;s like being able to run ffmpeg and change everything about anything while it&#39;s running&quot;, but even that&#39;s a gross simplification of what Norsk actually gives the customer.</p>
<p>I&#39;m really excited about what this means for the streaming industry and I&#39;m really excited to see where we end up taking it. We have a lot of capability in our core platform that isn&#39;t yet exposed in Norsk so we&#39;re only really starting out in our task to place that power in the hands of our clients.</p>
<p>Anyway - I&#39;ll be doing various technical blogs <em>about</em> Norsk and related subjects in the coming months over at the Norsk Blog, and I&#39;d be delighted if anybody were to join me over there for that.</p>
]]></description><link>http://codeofrob.com/entries/the-launching-of-a-product,-or-where-ive-been-for-the-last-few-years.html</link><guid isPermaLink="true">http://codeofrob.com/entries/the-launching-of-a-product,-or-where-ive-been-for-the-last-few-years.html</guid><dc:creator><![CDATA[Rob Ashton]]></dc:creator><pubDate>Thu, 01 Jun 2023 09:30:00 GMT</pubDate></item><item><title><![CDATA[Purerl Updates - A heap of ported modules]]></title><description><![CDATA[<p>Previous entries in this series: </p>
<ul>
<li><a href="/entries/purerl-updates---processes-and-self.html">Purerl Updates - Processes and Self</a></li>
<li><a href="/entries/purerl-updates---subscriptions.html">Purerl Updates - Subscriptions</a></li>
<li><a href="/entries/purerl-updates---untagged-unions.html">Purerl Updates - Untagged Unions</a></li>
<li><a href="/entries/purerl-updates---maxing-out-pinto-otp.html">Purerl Updates - Maxing out Pinto OTP</a></li>
<li><a href="/entries/purerl-updates---genstatem.htm">Purerl Updates - GenStatem</a></li>
</ul>
<p>One of the big advantages of using an existing language like Purescript when building out typed support for Erlang, is the presence of existing tooling and libraries for the language (such as language servers, package management, syntax highlighting, etc - as well as libraries for all the normal maths, string manipulation, date times, testing and all that).</p>
<p>That&#39;s not to say you get those things for free however, in a perfect world we could add libraries to our package set directly from the original repos - the litmus test for whether this is possible is &quot;Is there any Javascript in the original repo?&quot;. If there isn&#39;t then the library will work out of the box but if it has other dependencies that aren&#39;t yet in the package set then they will need adding to the package set too.</p>
<p>On top of that, one of the things we &#39;lack&#39; in Purerl is the Aff monad. We (as far as we can tell so far) don&#39;t need it because we&#39;re just not writing code that way - or rather with the presence of various means of performing async actions in Erlang it simply isn&#39;t necessary. This does mean that any library that brings in Aff (such as some of the popular testing frameworks) will need porting to use sometihng else unless somebody feels like porting <a href="https://github.com/purescript-contrib/purescript-aff/blob/main/src/Effect/Aff.js#L152">Aff</a>? No I thought not.</p>
<p>Consider the library <a href="https://github.com/purescript-contrib/purescript-parsing">purescript-parsing</a> which was needed recently to parse <a href="https://datatracker.ietf.org/doc/html/rfc8216">RFC8216</a>.</p>
<p>On the face of it, there is nothing but Purescript in <a href="https://github.com/purescript-contrib/purescript-parsing/tree/main/src/Text/Parsing/Parser">the repo</a> and the tests are incredibly simple, however it has a dependency on <a href="https://github.com/purescript-contrib/purescript-unicode">purescript-unicode</a> which whilst being entirely Purescript also, not only has a dependency on <a href="https://github.com/id3as/purescript-quickcheck">purescript-quickcheck</a> which absolutely does have some Erlang in it, but also generates Erlang that breaks the Erlang compiler because of &#39;complexity&#39;. (hard coded lists of unicode characters meant nested function calls all the way down).</p>
<p>Quickcheck needs the JS re-writing as Erlang, and then if you want to build unicode/parser independently and run <em>their</em> tests then they need their packages updating so they can pull the fork of quickcheck. Thankfully these libraries all (sensibly) have their tests written as a <em>main :: Effect Unit</em> rather than using a fancy testing library so the changes are very fast and easy to implement. As a result of running the test suite of course, some missing features were found in <a href="https://github.com/id3as/purescript-strings">purescript-strings</a> for which, thankfully built-in functions exist in Erlang so no hard work was required.</p>
<p>We also needed <a href="https://github.com/purescript/purescript-datetime">purescript-datetime</a> which has a lot of the underlying implementation built off of Javascript&#39;s date system and needed rewriting to use Erlangs. Since then this has become embedded in a lot of other packages because we consider things like Seconds and Milliseconds to be important primitives worth representing as something other than <em>Int</em> and defining our own newtypes everywhere doesn&#39;t make a lot of sense. If you&#39;re going to be using Datetime heavily then you probably also want to format dates and times so that means bringing in <a href="https://github.com/purescript-contrib/purescript-formatters">purescript-formatters</a> which has a dependency on parsing (cool, already ported!), but tests written against <em>Aff</em> for no good reason (That&#39;s fine, replaced them with good ol&#39; <a href="https://github.com/id3as/purescript-erl-test-eunit">purescript-erl-test-eunit</a>.</p>
<p>I guess what I&#39;m trying to say is that there are yaks all the way down, and that all of these libraries kindly written by other people don&#39;t come for <em>free</em>. On the bright side because we&#39;ve been actively writing Purescript for three years we&#39;ve brought across a lot of them ourselves already. The complete list of packages ported to the id3as organisation at this time of writing is:</p>
<ul>
<li><a href="https://github.com/id3as/purescript-these">purescript-these</a></li>
<li><a href="https://github.com/id3as/purescript-parsing">purescript-parsing</a></li>
<li><a href="https://github.com/id3as/purescript-pathy">purescript-pathy</a></li>
<li><a href="https://github.com/id3as/purescript-formatters">purescript-formatters</a></li>
<li><a href="https://github.com/id3as/purescript-unicode">purescript-unicode</a></li>
<li><a href="https://github.com/id3as/purescript-datetime">purescript-datetime</a></li>
<li><a href="https://github.com/id3as/purescript-quickcheck">purescript-quickcheck</a></li>
<li><a href="https://github.com/id3as/purescript-uri">purescript-uri</a></li>
<li><a href="https://github.com/id3as/purescript-sequences">purescript-sequences</a></li>
<li><a href="https://github.com/id3as/purescript-dagre">purescript-dagre</a></li>
<li><a href="https://github.com/id3as/purescript-longs">purescript-longs</a></li>
</ul>
<p>These will end up in the default package set over time so they can be referred to without needing to know where they are - but if you&#39;re venturing down the route of using Purescript and needing a package that doesn&#39;t exist, then check the <a href="https://github.com/purerl">Purerl org</a> and the <a href="https://github.com/id3as">Id3as</a> org to see if somebody hasn&#39;t already done the leg work!</p>
]]></description><link>http://codeofrob.com/entries/purerl-updates---a-heap-of-ported-modules.html</link><guid isPermaLink="true">http://codeofrob.com/entries/purerl-updates---a-heap-of-ported-modules.html</guid><dc:creator><![CDATA[Rob Ashton]]></dc:creator><pubDate>Thu, 28 Oct 2021 09:30:00 GMT</pubDate></item><item><title><![CDATA[Purerl Updates - GenStatem]]></title><description><![CDATA[<p>Seems we&#39;ve ended up with a small handful of posts about the latest Purerl updates! Great - that&#39;s about one for every reader, let&#39;s get cracking!</p>
<ul>
<li><a href="/entries/purerl-updates---processes-and-self.html">Purerl Updates - Processes and Self</a></li>
<li><a href="/entries/purerl-updates---subscriptions.html">Purerl Updates - Subscriptions</a></li>
<li><a href="/entries/purerl-updates---untagged-unions.html">Purerl Updates - Untagged Unions</a></li>
<li><a href="/entries/purerl-updates---maxing-out-pinto-otp.html">Purerl Updates - Maxing out Pinto OTP</a></li>
</ul>
<p>One of the big motivations for the big push on <a href="https://github.com/id3as/purescript-erl-pinto">purescript-erl-pinto</a> was to facillitate the addition of other OTP behaviours than GenServer.</p>
<p>One of our &quot;go-to&quot; servers is <a href="https://erlang.org/doc/man/gen_statem.html">gen_statem</a>. When writing any sort of implementation of a stateful network protocol for example, it is nice to model various steps of the protocol as &#39;states&#39; on which only certain types of message can be enacted. A gen_statem has a list of these possible states (as an atom in this case), as well as &#39;Data&#39; which is an arbitrary term.</p>
<p>The simplest example outside of this however, is the locked door. A door which is locked cannot be opened, and a door that is opened cannot be locked. If the door is open we can take the treasure behind the door and to unlock the door we need a key. This could be modelled with three states here, an</p>
<ul>
<li>Locked</li>
<li>Unlocked</li>
<li>Open</li>
</ul>
<p>Some of a plain ol&#39; gen_statem to represent this would look like this.</p>
<pre><code class="language-erlang">init([]) -&gt;
    {ok, locked , #{ key =&gt; &lt;&lt;&quot;open sesame&quot;&gt;&gt;, treasure =&gt; &lt;&lt;&quot;The moon is made of cheese&quot;&gt;&gt;}}.

handle_event({call,From}, { unlock, K1 }, locked, #{ key := K2, treasure := Secret }) 
  when K1 =:= K2 -&gt;
  {next_state, unlocked, #{ treasure =&gt; Secret }, [{reply, From, ok}]};

handle_event({call,From}, { unlock, _K1 }, locked, Data) 
  {keep_state, Data, [{reply, From, bad_key}]};

handle_event({call,From}, { unlock, _K1 }, unlocked, Data) 
  {keep_state, Data, [{reply, From, ok}]};

handle_event({call,From}, open, unlocked, Data) 
  {next_state, open, Data, [{reply, From, ok}]};
</code></pre>
<p>And so on and so forth. </p>
<p>A locked door has a key and a treasure, a call to &#39;unlock&#39; with the right key will give you an open door with just the &#39;treasure&#39;, a call to unlock with the wrong key will result in an error, a call to unlock when already unlocked is just fine thank-you and a door that is unlocked can be opened. A few things of note that we&#39;re not a <em>huge</em> fan of here. </p>
<ul>
<li>There is nothing to tie the current &#39;state&#39; with the &#39;data&#39;, thus there is nothing stopping a locked door from not having a key (oh dear!)</li>
<li>There are a <em>lot</em> of tuples with arbitrary atoms floating around and the possibility for typos is endless</li>
<li>States aren&#39;t defined up front, any arbitrary atom can be returned and we&#39;ll now be in that state</li>
</ul>
<p>We could be generous and say that two of these are actually a feature and not a bug, but beauty is in the eye of the beholder and if you&#39;re a fan of type systems then this has all the beauty of my macaroni art from pre-school.</p>
<p>From a Purescript perspective, it&#39;d be nice if we could tie the current state with &quot;state specific data&quot; using an ADT, as well as have some state that is common to all.</p>
<pre><code class="language-haskell"><span class="hljs-class"><span class="hljs-keyword">data</span> <span class="hljs-type">State</span> </span>
  = <span class="hljs-type">Locked</span> { key :: <span class="hljs-type">String</span>, treasure :: <span class="hljs-type">String</span> }
  | <span class="hljs-type">Unlocked</span> { treasure :: <span class="hljs-type">String</span> }
  | <span class="hljs-type">Open</span>
</code></pre>
<pre><code class="language-haskell"><span class="hljs-title">startLink</span> :: <span class="hljs-type">Effect</span> (<span class="hljs-type">StartLinkResult</span> <span class="hljs-type">DoorLockPid</span>)
<span class="hljs-title">startLink</span> = <span class="hljs-keyword">do</span>
  <span class="hljs-type">GenStatem</span>.startLink $ <span class="hljs-type">GenStatem</span>.defaultSpec init
  <span class="hljs-keyword">where</span>
    init = pure $ <span class="hljs-type">InitOk</span> (<span class="hljs-type">Locked</span> { key: <span class="hljs-string">&quot;open sesame&quot;</span>, treasure: <span class="hljs-string">&quot;the moon is made of cheese&quot;</span> }) {}
</code></pre>
<p>Now, the only problem with our new <em>State</em> is that the extra data bundled with it is means that it can&#39;t be used directly as a &#39;state&#39; in gen_statem because each variant would be a new state!</p>
<p>A typeclass provided therefore be able to extract a &#39;stateid&#39; to pass to the underlying gen_statem implementation</p>
<pre><code class="language-haskell"><span class="hljs-class"><span class="hljs-keyword">data</span> <span class="hljs-type">StateId</span></span>
  = <span class="hljs-type">StateIdLocked</span>
  | <span class="hljs-type">StateIdUnlocked</span>
  | <span class="hljs-type">StateIdOpen</span>

<span class="hljs-title">derive</span> <span class="hljs-keyword">instance</span> eqStateId :: <span class="hljs-type">Eq</span> <span class="hljs-type">StateId</span>
<span class="hljs-class">
<span class="hljs-keyword">instance</span> stateHasStateId :: <span class="hljs-type">HasStateId</span> <span class="hljs-type">StateId</span> <span class="hljs-type">State</span> <span class="hljs-keyword">where</span></span>
  getStateId (<span class="hljs-type">Locked</span> _) = <span class="hljs-type">StateIdLocked</span>
  getStateId (<span class="hljs-type">Unlocked</span> _) = <span class="hljs-type">StateIdUnlocked</span>
  getStateId (<span class="hljs-type">Open</span> _) = <span class="hljs-type">StateIdOpen</span></code></pre>
<p>A default implementation could exist of course to simply extract an atom from the underlying representation, building that is left as an exercise for the reader..</p>
<p>Anyway, just like with GenServer and Supervisor, we can represent a GenStatem with a Pid and a Type in order to communicate with it and build up various callbacks and such. The type specs are quite daunting beause GenStatem has quite a few different &#39;message types&#39; - most of thes can be ignored and set to Void/Unit until needed.</p>
<pre><code class="language-haskell"><span class="hljs-class"><span class="hljs-keyword">newtype</span> <span class="hljs-type">StatemType</span> :: <span class="hljs-type">Type</span> -&gt; <span class="hljs-type">Type</span> -&gt; <span class="hljs-type">Type</span> -&gt; <span class="hljs-type">Type</span> -&gt; <span class="hljs-type">Type</span> -&gt; <span class="hljs-type">Type</span> -&gt; <span class="hljs-type">Type</span> -&gt; <span class="hljs-type">Type</span></span>
<span class="hljs-class"><span class="hljs-keyword">newtype</span> <span class="hljs-type">StatemType</span> info internal timerName timerContent commonData stateId state</span>
  = <span class="hljs-type">StatemType</span> <span class="hljs-type">Void</span>

<span class="hljs-class"><span class="hljs-keyword">newtype</span> <span class="hljs-type">StatemPid</span> :: <span class="hljs-type">Type</span> -&gt; <span class="hljs-type">Type</span> -&gt; <span class="hljs-type">Type</span> -&gt; <span class="hljs-type">Type</span> -&gt; <span class="hljs-type">Type</span> -&gt; <span class="hljs-type">Type</span> -&gt; <span class="hljs-type">Type</span> -&gt; <span class="hljs-type">Type</span></span>
<span class="hljs-class"><span class="hljs-keyword">newtype</span> <span class="hljs-type">StatemPid</span> info internal timerName timerContent commonData stateId state</span>
  = <span class="hljs-type">StatemPid</span> (<span class="hljs-type">Process</span> info)</code></pre>
<p>Our very simple DoorLock Genstatem which doesn&#39;t have any messages outside of direct &#39;calls&#39; could be defined as </p>
<pre><code class="language-haskell"><span class="hljs-class"><span class="hljs-keyword">type</span> <span class="hljs-type">DoorlockType</span> = <span class="hljs-type">StatemType</span> <span class="hljs-type">Unit</span> <span class="hljs-type">Unit</span> <span class="hljs-type">Unit</span> <span class="hljs-type">Unit</span> {} <span class="hljs-type">StateId</span> <span class="hljs-type">State</span></span>
<span class="hljs-class"><span class="hljs-keyword">type</span> <span class="hljs-type">DoorlockPid</span> = <span class="hljs-type">StatemPid</span> <span class="hljs-type">Unit</span> <span class="hljs-type">Unit</span> <span class="hljs-type">Unit</span> <span class="hljs-type">Unit</span> {} <span class="hljs-type">StateId</span> <span class="hljs-type">State</span></span></code></pre>
<p>With these types defined, a semi-complete implementation of our door-lock GenStatem could therefore look like</p>
<pre><code class="language-haskell"><span class="hljs-title">serverName</span> :: <span class="hljs-type">RegistryName</span> <span class="hljs-type">DoorlockType</span>
<span class="hljs-title">serverName</span> = <span class="hljs-type">Local</span> $ atom <span class="hljs-string">&quot;doorlock&quot;</span>

<span class="hljs-title">startLink</span> :: <span class="hljs-type">Effect</span> (<span class="hljs-type">StartLinkResult</span> <span class="hljs-type">DoorlockPid</span>)
<span class="hljs-title">startLink</span> = 
  <span class="hljs-type">Statem</span>.startLink $ <span class="hljs-type">Statem</span>.defaultSpec init { name = <span class="hljs-type">Just</span> serverName } 

<span class="hljs-class"><span class="hljs-keyword">data</span> <span class="hljs-type">UnlockResult</span> = <span class="hljs-type">Unlocked</span> | <span class="hljs-type">BadCode</span> </span>

<span class="hljs-title">unlock</span> :: <span class="hljs-type">String</span> -&gt; <span class="hljs-type">Effect</span> <span class="hljs-type">UnlockResult</span>
<span class="hljs-title">unlock</span> k1 = <span class="hljs-type">GenStatem</span>.call (<span class="hljs-type">ByName</span> serverName) 
  \from (<span class="hljs-type">Locked</span> { key: k2 } _ = 
    <span class="hljs-keyword">if</span> k2 == k1 <span class="hljs-keyword">then</span> <span class="hljs-keyword">do</span>
      <span class="hljs-keyword">let</span> actions = <span class="hljs-type">GenStatem</span>.newActions # <span class="hljs-type">GenStatem</span>.addReply (<span class="hljs-type">GenStatem</span>.reply from <span class="hljs-type">Unlocked</span>)
      pure <span class="hljs-type">EventNextStateWithActions</span> (<span class="hljs-type">Unlocked</span> { treasure }) {} actions
    <span class="hljs-keyword">else</span> <span class="hljs-keyword">do</span>
      <span class="hljs-keyword">let</span> actions = <span class="hljs-type">GenStatem</span>.newActions # <span class="hljs-type">GenStatem</span>.addReply (<span class="hljs-type">GenStatem</span>.reply from <span class="hljs-type">BadCode</span>)
      pure $ <span class="hljs-type">EventKeepStateAndDataWithActions</span> actions
</code></pre>
<p>The GenStatem functionality in Pinto is being used in a few places in our codebases now, but it is not complete. There are some hand-wavey bits around timers and messaging that will get fixed when somebody needs it, but the pattern and general types are pretty much now in place. Various callbacks can be supplied by overriding the default spec, those callbacks will receive certain kinds of messages that will need adding to the type signatures and various return values can be built up by using the functions provided in the GenStatem module.</p>
<p>There are other kinds of Genserver available that could do with representations in Pinto and as we saw in the last entry, now we have a generic way of representing &#39;pids&#39; and &#39;types&#39; that can supply and enforce their own internal messages, it should be possible to do this without making any substantial changes to pinto itself.</p>
<h2 id="a-note-on-pintos-future">A note on Pinto&#39;s future</h2>
<p>Pinto is now &#39;conceptually&#39; pretty complete and hopefully shouldn&#39;t undergo any more major changes. The types that have been added can be used to describe pretty much any running proces and various functionalities that can be exposed to interact with those proceses - from the simple &quot;This process has a state and can receive messages&quot; to &quot;This process has a state, can receive this type of video stream and this type of audio stream, send these messages on a timer...&quot; and then be stuck into Supervisors in the same way as any other server.</p>
<p>There are probably better ways of representing this in Purescript by deviating further from OTP itself and re-imagining a more Purescript central means of modelling these things. Eventually somebody is going to take the plunge and do this and it probably won&#39;t be us. Should this happen, I don&#39;t think it&#39;ll take long to move away from Pinto and to it - so if anybody fancies the task...</p>
]]></description><link>http://codeofrob.com/entries/purerl-updates---genstatem.html</link><guid isPermaLink="true">http://codeofrob.com/entries/purerl-updates---genstatem.html</guid><dc:creator><![CDATA[Rob Ashton]]></dc:creator><pubDate>Tue, 26 Oct 2021 09:30:00 GMT</pubDate></item><item><title><![CDATA[Purerl Updates - maxing out Pinto OTP]]></title><description><![CDATA[<p>Yes, another blog post about Purerl, following on from</p>
<ul>
<li><a href="/entries/purerl-updates---processes-and-self.html">Purerl Updates - Processes and Self</a></li>
<li><a href="/entries/purerl-updates---subscriptions.html">Purerl Updates - Subscriptions</a></li>
<li><a href="/entries/purerl-updates---untagged-unions.html">Purerl Updates - Untagged Unions</a></li>
</ul>
<p>When I first threw together <a href="https://github.com/id3as/purescript-erl-pinto">Pinto</a>, it was with the aim that there simply be a usable path for building supervision trees and gen servers, and not that we would have access to the full functionality of those things straight out of the gate. This proved to be a sensible choice because as we learned more about how we would like to write code in Purescript built around various messaging mechanisms it also turned out that this code would need to evolve more than a few times before we were all truly happy with the model.</p>
<p>A lot of usable application code was written with this &quot;V1&quot; pass, but it was always known that eventually we would want to not only have access to other &quot;gen&quot; models (such as statem), but the bullet would need biting and the model would need expanding to allow us to use the full gamut of functionality exposed by gen_server.</p>
<p>Thankfully, it turns out that the general concepts that had evolved during the development and real-world use of V1 carried over, and the changes as far as the end-user is concerned are largely additive. (Note: I didn&#39;t do most of the work on V2, that was <a href="https://github.com/philipstears">@philipstears</a> and <a href="https://github.com/adrianroe">@adrianroe</a>, so kudos to them on gathering the will for it).</p>
<h2 id="the-types">The types</h2>
<p>In V1 Pinto, the types around the spinning up of processes was very GenServer focused</p>
<pre><code class="language-haskell"><span class="hljs-class"><span class="hljs-keyword">data</span> <span class="hljs-type">ServerName</span> state msg = <span class="hljs-type">Local</span> <span class="hljs-type">Atom</span></span>
                          | <span class="hljs-type">Global</span> <span class="hljs-type">GlobalName</span>
                          | <span class="hljs-type">Via</span> <span class="hljs-type">NativeModuleName</span> <span class="hljs-type">Foreign</span></code></pre>
<p>Not only that, but the result of calling the various <em>startLinks</em> for Supervisors/GenServers was very simplistic - losing any information about whatever the process was that was started. (Hello Raw.Pid)</p>
<pre><code class="language-haskell"><span class="hljs-class"><span class="hljs-keyword">data</span> <span class="hljs-type">StartLinkResult</span></span>
  = <span class="hljs-type">Ok</span> <span class="hljs-type">Pid</span>
  | <span class="hljs-type">Ignore</span>
  | <span class="hljs-type">AlreadyStarted</span> <span class="hljs-type">Pid</span>
  | <span class="hljs-type">Failed</span> <span class="hljs-type">Foreign</span></code></pre>
<p>As a result, this meant things like Supervisor had their ServerName defined as </p>
<pre><code class="language-haskell"><span class="hljs-class"><span class="hljs-keyword">type</span> <span class="hljs-type">SupervisorName</span> = <span class="hljs-type">ServerName</span> <span class="hljs-type">Unit</span> <span class="hljs-type">Unit</span></span></code></pre>
<p>Which isn&#39;t <em>wrong</em> as such, but is completely pointless. State and Msg are GenServer constructs and they aren&#39;t even the only ones we need for a GenServer which is about to get a revamp anway. The answer (as it often does), lies in adding type parameters - while we&#39;re at it, changing the API to use an Either because that&#39;s a good way to represent success and failure.</p>
<pre><code class="language-haskell"><span class="hljs-class"><span class="hljs-keyword">data</span> <span class="hljs-type">NotStartedReason</span> serverProcess</span>
  = <span class="hljs-type">Ignore</span>
  | <span class="hljs-type">AlreadyStarted</span> serverProcess
  | <span class="hljs-type">Failed</span> <span class="hljs-type">Foreign</span>

<span class="hljs-class"><span class="hljs-keyword">type</span> <span class="hljs-type">StartLinkResult</span> serverProcess</span>
  = <span class="hljs-type">Either</span> (<span class="hljs-type">NotStartedReason</span> serverProcess) serverProcess</code></pre>
<p>We can&#39;t add constraints to the type definion itself, but we can enforce that when these things are used that <em>HasPid serverProcess =&gt;</em>, which is what Pinto will do in most of its APIs. By doing this, we can have GenServers export a new type (ServerPid state msg) and Supervisors export their own type (SupervisorPid) which both have Raw.Pid underlying them, but GenServer can also <em>(HasProcess msg (ServerPid state msg))</em> which Just Makes Sense.</p>
<p>A similar thing can be done to ServerName</p>
<pre><code class="language-haskell"><span class="hljs-class"><span class="hljs-keyword">data</span> <span class="hljs-type">RegistryName</span> :: <span class="hljs-type">Type</span> -&gt; <span class="hljs-type">Type</span></span>
<span class="hljs-class"><span class="hljs-keyword">data</span> <span class="hljs-type">RegistryName</span> serverType</span>
  = <span class="hljs-type">Local</span> <span class="hljs-type">Atom</span>
  | <span class="hljs-type">Global</span> <span class="hljs-type">Foreign</span>
  | <span class="hljs-type">Via</span> <span class="hljs-type">NativeModuleName</span> <span class="hljs-type">Foreign</span></code></pre>
<p>Why would we want that? Because calls into running processes (such as GenServer.call or Supervisor.startChild) might like to know type information in order to enforce some level of correctness, and while we&#39;re at it we can support doing this either either the Pid gained from startLink, or with the registered name of that child</p>
<pre><code class="language-haskell"><span class="hljs-class"><span class="hljs-keyword">data</span> <span class="hljs-type">RegistryReference</span> :: <span class="hljs-type">Type</span> -&gt; <span class="hljs-type">Type</span> -&gt; <span class="hljs-type">Type</span></span>
<span class="hljs-class"><span class="hljs-keyword">data</span> <span class="hljs-type">RegistryReference</span> serverPid serverType</span>
  = <span class="hljs-type">ByPid</span> serverPid
  | <span class="hljs-type">ByName</span> (<span class="hljs-type">RegistryName</span> serverType)</code></pre>
<p>Now this has been done, we&#39;re free to re-write Supervisor (or indeed, as we will see, split it into two different modules), and re-write GenServer with all the types we want without that leaking across implementations.</p>
<h2 id="genservers">GenServers</h2>
<p>Consider the following very boring GenServer in V1 that starts up, subscribes to a bus, and receives messages via handleInfo</p>
<pre><code class="language-haskell"><span class="hljs-class"><span class="hljs-keyword">type</span> <span class="hljs-type">BookWatchingStartArgs</span> = {}</span>
<span class="hljs-class"><span class="hljs-keyword">type</span> <span class="hljs-type">State</span> = {}</span>

<span class="hljs-class"><span class="hljs-keyword">data</span> <span class="hljs-type">Msg</span> = <span class="hljs-type">BookMsg</span> <span class="hljs-type">BookEvent</span> </span>

<span class="hljs-title">serverName</span> :: <span class="hljs-type">ServerName</span> <span class="hljs-type">State</span> <span class="hljs-type">Msg</span>
<span class="hljs-title">serverName</span> = <span class="hljs-type">Local</span> $ atom <span class="hljs-string">&quot;handle_info_example&quot;</span>

<span class="hljs-title">startLink</span> :: <span class="hljs-type">BookWatchingStartArgs</span> -&gt; <span class="hljs-type">Effect</span> <span class="hljs-type">StartLinkResult</span>
<span class="hljs-title">startLink</span> args =
  <span class="hljs-type">Gen</span>.buildStartLink serverName (init args) $ <span class="hljs-type">Gen</span>.defaultStartLink { handleInfo = handleInfo }

<span class="hljs-title">currentState</span> :: <span class="hljs-type">Effect</span> <span class="hljs-type">State</span>
<span class="hljs-title">currentState</span> = <span class="hljs-type">Gen</span>.call serverName \state -&gt; pure $ <span class="hljs-type">CallReply</span> state state

<span class="hljs-title">init</span> :: <span class="hljs-type">BookWatchingStartArgs</span> -&gt; <span class="hljs-type">Gen</span>.<span class="hljs-type">Init</span> <span class="hljs-type">State</span> <span class="hljs-type">Msg</span>
<span class="hljs-title">init</span> args = <span class="hljs-keyword">do</span>
  self &lt;- <span class="hljs-type">Gen</span>.self
  _ &lt;- <span class="hljs-type">Gen</span>.lift $ <span class="hljs-type">SimpleBus</span>.subscribe <span class="hljs-type">BookLibrary</span>.bus $ <span class="hljs-type">BookMsg</span> &gt;&gt;&gt; send self
  pure $ {}


<span class="hljs-title">handleInfo</span> :: <span class="hljs-type">Msg</span> -&gt; <span class="hljs-type">State</span> -&gt; <span class="hljs-type">Gen</span>.<span class="hljs-type">HandleInfo</span> <span class="hljs-type">State</span> <span class="hljs-type">Msg</span>
<span class="hljs-title">handleInfo</span> msg state = <span class="hljs-keyword">do</span>
  <span class="hljs-keyword">case</span> msg <span class="hljs-keyword">of</span>
    <span class="hljs-type">BookMsg</span> bookEvent -&gt; 
      <span class="hljs-comment">-- <span class="hljs-doctag">TODO:</span> Something with bookEvent</span>
      pure $ <span class="hljs-type">CastNoReply</span> state
</code></pre>
<p>There are a few things of note here</p>
<ul>
<li>The GenServer <em>has</em> to have a name (not strictly true but..), this isn&#39;t really necessary for lot of  <em>simple_one_for_one</em> for example</li>
<li>How can &#39;init&#39; fail?</li>
<li>How does one stop this gen server from inside the gen server?</li>
<li>How does one defer a reply in response to a &#39;call&#39; (Usually gen_server would give you a &#39;from&#39; argument, this has been dropped here)</li>
<li>The use of &#39;Gen.self&#39; (see also: <a href="/entries/purerl-updates---processes-and-self.html">Purerl Updates - Processes and Self</a></li>
<li>How does one do a handle_continue, and what is its type going to be?</li>
</ul>
<p>As we can see, this largely comes down to missing items from the surface area of the gen server rather than a fundamental design flaw, but nevertheless there are some breaking changes to get to the point where these things are supposed. </p>
<h2 id="starting-a-genserver">Starting a GenServer</h2>
<p>A few things need to change here</p>
<ul>
<li>A GenServer can ask to &#39;continue&#39; an exchange by returning the current operation and re-entering with a message sent internally - we need a type for this</li>
<li>A GenServer can ask to &#39;shutdown&#39;, and can supply a &#39;reason&#39; for that shutdown that can be intercepted elsewhere/internally and it&#39;d be nice if that was typed</li>
<li>The return result of the startLink isn&#39;t typed <em>at all</em>, this should be a Pid of some sort that encapsulates that types of messages this GenServer can receive</li>
<li>Name should be optional</li>
</ul>
<p>Thus, we need two extra types added to our ServerName (Cont and Stop), and StartLinkResult actually needs to be typed around some sort of Pid.</p>
<pre><code class="language-haskell"><span class="hljs-title">serverName</span> :: <span class="hljs-type">RegistryName</span> (<span class="hljs-type">GenServer</span>.<span class="hljs-type">ServerType</span> <span class="hljs-type">Unit</span> <span class="hljs-type">Unit</span> <span class="hljs-type">Msg</span> <span class="hljs-type">State</span>)
<span class="hljs-title">serverName</span> = <span class="hljs-type">Local</span> $ atom <span class="hljs-string">&quot;handle_info_example&quot;</span>

<span class="hljs-title">startLink</span> :: <span class="hljs-type">BookWatchingStartArgs</span> -&gt; <span class="hljs-type">Effect</span> (<span class="hljs-type">StartLinkResult</span> (<span class="hljs-type">GenServer</span>.<span class="hljs-type">ServerPid</span> <span class="hljs-type">Unit</span> <span class="hljs-type">Unit</span> <span class="hljs-type">Msg</span> <span class="hljs-type">State</span>))
<span class="hljs-title">startLink</span> args = <span class="hljs-type">GenServer</span>.startLink $ (<span class="hljs-type">GenServer</span>.defaultSpec (init args)) { name = <span class="hljs-type">Just</span> serverName, handleInfo = <span class="hljs-type">Just</span> handleInfo }

<span class="hljs-title">init</span> :: <span class="hljs-type">BookWatchingStartArgs</span> -&gt; <span class="hljs-type">GenServer</span>.<span class="hljs-type">InitFn</span> <span class="hljs-type">Unit</span> <span class="hljs-type">Unit</span> <span class="hljs-type">Msg</span> <span class="hljs-type">State</span> 
<span class="hljs-title">init</span> _args = <span class="hljs-keyword">do</span>
  _ &lt;- <span class="hljs-type">SimpleBus</span>.subscribe <span class="hljs-type">BookLibrary</span>.bus <span class="hljs-type">BookMsg</span> 
  pure $ <span class="hljs-type">InitOk</span> {}</code></pre>
<p>So</p>
<ul>
<li>serverName is now a RegistryName parameterised with <em>GenServer.ServerType (Cont Stop Msg State)</em></li>
<li>GenServer.startLink now simply takes a record full of config for which a default can be summoned with defaultSpec</li>
<li>serverName is completely optional (as is handleInfo, both are Maybes to indicate this)</li>
<li>StartLinkResult is now parameterised with the type of Pid we&#39;re starting with, in this case a GenServer.ServerPid (Cont Stop Msg State)</li>
<li>init now returns an indication as to whether it has actually succeeded or not..</li>
</ul>
<p>We&#39;ll also note that with the addition of <a href="/entries/purerl-updates---processes-and-self.html">HasSelf</a>, we can now use subscribe without liftEffect, just relying on ambient context to get the messages sent to <em>self</em> (See also <a href="/entries/purerl-updates---subscriptions.html">Subscriptions</a>)</p>
<p>Our handleInfo has changed as well (as has every other callback, but in exactly the same way) as it needs to also include all the additional type information for this GenServer</p>
<pre><code class="language-haskell"><span class="hljs-title">handleInfo</span> :: <span class="hljs-type">GenServer</span>.<span class="hljs-type">InfoFn</span> <span class="hljs-type">Unit</span> <span class="hljs-type">Unit</span> <span class="hljs-type">Msg</span> <span class="hljs-type">State</span>
<span class="hljs-title">handleInfo</span> msg state = 
  <span class="hljs-keyword">case</span> msg <span class="hljs-keyword">of</span>
   <span class="hljs-type">BookMsg</span> bookEvent -&gt; 
      <span class="hljs-comment">-- <span class="hljs-doctag">TODO:</span> Something with bookEvent</span>
      pure $ <span class="hljs-type">GenServer</span>.return state</code></pre>
<p>Conceptually, nothing has really changed in our basic use cases except more types have been added to various signatures to make additional functionality possible (which we can default to <em>Unit</em> until we need them), as well as all of the callbacks now operating inside a <em>HasSelf msg =&gt;</em> (actually a <em>ResultT cont stop msg state</em>), so that all of the type information for this GenServer is available at all times.</p>
<p>A heap of methods now hang off GenServer to help return the appropriate responses from the various callbacks (CallFn, CastFn, InfoFn, ContFn, TerminateFn) which are all typed safely around whatever we&#39;ve declared in our signature.</p>
<p>It&#39;s certainly a bit more verbose because of all of these extra types, but typically what ends up happening in our code is that we have business-process specific monads written which sit <em>inside</em> a GenServer and only expose the bits we need so that we don&#39;t have to write <em>Unit Unit Unit State</em> repeatedly. A lesson from the last couple of years with typed FP - with flexibility comes verbosity...</p>
<h2 id="supervisors">Supervisors</h2>
<p>Supervisors in V1 were okay for most cases except <em>simple_one_for_one</em>. </p>
<ul>
<li>A reading of the documentation for Erlang OTP reveals that in most cases, both the arguments <em>and</em> the return value of API calls into <em>supervisor:** are special-cased for *simple_one_for_one</em></li>
<li>There was no way in V1 of tying the construction of the simple_one_for_one supervisor and the subsequent calls to <em>start_child</em> together, thus it was very hand-wavey with regards to type safety</li>
</ul>
<p>The solution? The solution is to have two modules - one for &quot;simple_one_for_one&quot; (<em>Pinto.Supervisor.SimpleOneForOne</em>) and one for everything else (<em>Pinto.Supervisor</em>). This makes the API much easier because the return values of functions stop being dependent on the type of supervisor being ran (in Purescript at least) and we can disregard the special cases in both modules because the code doesn&#39;t allow for us to end up in situations where we&#39;re calling one type of supervisors with another&#39;s pid.</p>
<p>Just like with GenServers, we&#39;ll see that these are constructed around <em>RegistryName</em> and <em>StartLinkResult pid</em>, this is once again so that we have typed pids available for invocation into the various APIs in a standardised manner.</p>
<p>Normal supervisors (from <a href="https://github.com/id3as/demo-ps">demo-ps</a>). </p>
<pre><code class="language-haskell"><span class="hljs-title">startLink</span> :: <span class="hljs-type">Effect</span> (<span class="hljs-type">StartLinkResult</span> <span class="hljs-type">SupervisorPid</span>)
<span class="hljs-title">startLink</span> = <span class="hljs-keyword">do</span>
  <span class="hljs-type">Supervisor</span>.startLink (<span class="hljs-type">Just</span> $ <span class="hljs-type">Local</span> $ atom <span class="hljs-string">&quot;example_sup&quot;</span>) init

<span class="hljs-title">init</span> :: <span class="hljs-type">Effect</span> <span class="hljs-type">SupervisorSpec</span>
<span class="hljs-title">init</span> = <span class="hljs-keyword">do</span>
  connectionString &lt;- <span class="hljs-type">BookConfig</span>.connectionString
  webPort &lt;- <span class="hljs-type">BookConfig</span>.webPort
  pure
    { flags:
        { strategy: <span class="hljs-type">OneForOne</span>
        , intensity: <span class="hljs-number">1</span>
        , period: <span class="hljs-type">Seconds</span> <span class="hljs-number">5.0</span>
        }
    , childSpecs:
        (worker <span class="hljs-string">&quot;book_web&quot;</span> $ <span class="hljs-type">BookWeb</span>.startLink { webPort })
        : (worker <span class="hljs-string">&quot;empty_server&quot;</span> $ <span class="hljs-type">EmptyGenServer</span>.startLink {})
        : (worker <span class="hljs-string">&quot;book_library&quot;</span> $ <span class="hljs-type">BookLibrary</span>.startLink { connectionString })
        : (worker <span class="hljs-string">&quot;handle_info_example&quot;</span> $ <span class="hljs-type">HandleInfoExample</span>.startLink {})
        : (worker <span class="hljs-string">&quot;monitor_example&quot;</span> $ <span class="hljs-type">MonitorExample</span>.startLink {})
        : nil
    }
<span class="hljs-title">worker</span> ::
  <span class="hljs-keyword">forall</span> childProcess.
  <span class="hljs-type">HasPid</span> childProcess =&gt;
  <span class="hljs-type">String</span> -&gt; <span class="hljs-type">Effect</span> (<span class="hljs-type">StartLinkResult</span> childProcess) -&gt; <span class="hljs-type">ErlChildSpec</span>
<span class="hljs-title">worker</span> id start =
  spec
    { id
    , childType: <span class="hljs-type">Worker</span>
    , start
    , restartStrategy: <span class="hljs-type">RestartTransient</span>
    , shutdownStrategy: <span class="hljs-type">ShutdownTimeout</span> $ <span class="hljs-type">Milliseconds</span> <span class="hljs-number">5000.0</span>
    }
</code></pre>
<p>You&#39;ll note that the server has a name (Local $ atom &quot;example_sup&quot;), calls to startChild/terminateChild/deleteChild can be made with <em>ByName $ Local $ atom &quot;example_sup&quot;</em> if we so needed. In the case of simple_one_for_one (below), this server name has the start args and pid type of the children encoded in it so that calls to startChild/etc are typed.</p>
<p>simple_one_for_one:</p>
<pre><code class="language-haskell"><span class="hljs-title">serverName</span> :: <span class="hljs-type">RegistryName</span> (<span class="hljs-type">OneForOne</span>.<span class="hljs-type">SupervisorType</span> <span class="hljs-type">OneForOneGenServerStartArgs</span> <span class="hljs-type">OneForOneGenPid</span>)
<span class="hljs-title">serverName</span> = <span class="hljs-type">Local</span> $ atom $ <span class="hljs-string">&quot;one_for_one_example&quot;</span>

<span class="hljs-title">startLink</span> :: <span class="hljs-type">Effect</span> (<span class="hljs-type">StartLinkResult</span> (<span class="hljs-type">OneForOne</span>.<span class="hljs-type">SupervisorPid</span> <span class="hljs-type">OneForOneGenServerStartArgs</span> <span class="hljs-type">OneForOneGenPid</span>))
<span class="hljs-title">startLink</span> = <span class="hljs-type">OneForOne</span>.startLink (<span class="hljs-type">Just</span> serverName) init

<span class="hljs-title">init</span> :: <span class="hljs-type">Effect</span> (<span class="hljs-type">ChildSpec</span> <span class="hljs-type">OneForOneGenServerStartArgs</span> <span class="hljs-type">OneForOneGenPid</span>)
<span class="hljs-title">init</span> =
  pure { intensity: <span class="hljs-number">100</span>
    , period: <span class="hljs-type">Seconds</span> <span class="hljs-number">60.0</span>
    , childType: <span class="hljs-type">Worker</span>
    , start: <span class="hljs-type">OneForOneGen</span>.startLink
    , restartStrategy: <span class="hljs-type">RestartTransient</span>
    , shutdownStrategy: <span class="hljs-type">ShutdownTimeout</span> $ <span class="hljs-type">Milliseconds</span> <span class="hljs-number">5000.0</span>
  } 

<span class="hljs-title">startClient</span> :: <span class="hljs-type">OneForOneGenServerStartArgs</span> -&gt; <span class="hljs-type">Effect</span> <span class="hljs-type">OneForOneGenPid</span>
<span class="hljs-title">startClient</span> args = <span class="hljs-keyword">do</span>
  crashIfChildNotStarted &lt;$&gt; <span class="hljs-type">Sup</span>.startChild (<span class="hljs-type">ByName</span> serverName) args
</code></pre>
<h2 id="monitors">Monitors</h2>
<p>With untagged unions, it is entirely possible now to use monitors directly from <a href="https://github.com/id3as/purescript-erl-kernel">erl-kernel</a>, if our process is either single-purpose or is already using untagged unions with say, gun. However, in a lot of cases it still makes sense to use the message router in Pinto for this because we want our code to maintain simplicity with a simple ADT. For this convenience an implementation of Monitor still exists inside Pinto which implements this for us.</p>
<p>For anything that has a Pid, and assuming we&#39;re inside something that <em>HasSelf</em>, we can call</p>
<pre><code class="language-haskell"><span class="hljs-title">ref</span> &lt;- <span class="hljs-type">Monitor</span>.monitor pid <span class="hljs-type">ProcessDown</span></code></pre>
<p>where ProcessDown is a constructor that takes a <em>Pinto.Monitor.MonitorMsg</em></p>
<pre><code class="language-haskell"><span class="hljs-class"><span class="hljs-keyword">data</span> <span class="hljs-type">MyMsg</span> </span>
  = <span class="hljs-type">Tick</span>
  | <span class="hljs-type">ProcessDown</span> <span class="hljs-type">Monitor</span>.<span class="hljs-type">MonitorMsg</span></code></pre>
<p>A MonitorMsg is presently defined as </p>
<pre><code class="language-haskell"><span class="hljs-class"><span class="hljs-keyword">type</span> <span class="hljs-type">MonitorObject</span></span>
  = <span class="hljs-type">Foreign</span>
<span class="hljs-class"><span class="hljs-keyword">type</span> <span class="hljs-type">MonitorInfo</span></span>
  = <span class="hljs-type">Foreign</span>
<span class="hljs-class"><span class="hljs-keyword">data</span> <span class="hljs-type">MonitorType</span></span>
  = <span class="hljs-type">Process</span>
  | <span class="hljs-type">Port</span>
<span class="hljs-class"><span class="hljs-keyword">data</span> <span class="hljs-type">MonitorMsg</span></span>
  = <span class="hljs-type">Down</span> (<span class="hljs-type">MR</span>.<span class="hljs-type">RouterRef</span> <span class="hljs-type">MonitorRef</span>) <span class="hljs-type">MonitorType</span> <span class="hljs-type">MonitorObject</span> <span class="hljs-type">MonitorInfo</span></code></pre>
<p>Which will need expanding should anybody actually need that information. Because we have a router sat in the way, the usual usage of monitor is to pass all of the information we need into the message that will be sent to us and ignore the MonitorMsg entirely</p>
<pre><code class="language-haskell"><span class="hljs-title">ref</span> &lt;- <span class="hljs-type">Monitor</span>.monitor pid (const $ <span class="hljs-type">ProcessDown</span> pid)</code></pre>
<p>where</p>
<pre><code class="language-haskell"><span class="hljs-class"><span class="hljs-keyword">data</span> <span class="hljs-type">MyMsg</span> </span>
  = <span class="hljs-type">Tick</span>
  | <span class="hljs-type">ProcessDown</span> <span class="hljs-type">Pid</span></code></pre>
<p>Pull requests are accepted should somebody want to make the effort to expand those types into reality for some reason.</p>
<h2 id="timers">Timers</h2>
<p>Timers have also had a slight change in line with the new <em>HasSelf</em> typeclass and thoughts around subscriptions, as well as importing the recently ported DateTime libraries so that we have sensible duration types available to us.</p>
<p>So instead of</p>
<pre><code class="language-haskell"><span class="hljs-title">me</span> &lt;- self
<span class="hljs-title">liftEffect</span> $ <span class="hljs-type">Timer</span>.sendEvery <span class="hljs-number">1000</span> me <span class="hljs-type">Tick</span></code></pre>
<p>We have the far simpler</p>
<pre><code class="language-haskell"><span class="hljs-type">Timer</span>.sendEvery (<span class="hljs-type">Milliseconds</span> <span class="hljs-number">1000.0</span>) <span class="hljs-type">Tick</span></code></pre>
<p>This will probably be moved to <a href="https://github.com/id3as/purescript-erl-kernel">erl-kernel</a> in time, because it no longer does anything special and looks exactly like the underlying API.</p>
<h2 id="summary">Summary</h2>
<p>Conceptually not a lot has changed and yet we&#39;ve ended up in a place where we can use the full range of functionalities exposed by GenServers and Supervisors in a type-safe manner, we can chalk that up as a win - especially as it means this <a href="https://github.com/id3as/purescript-erl-pinto/issues/2">Github issue</a> from March 2019 can finally be closed.</p>
]]></description><link>http://codeofrob.com/entries/purerl-updates---maxing-out-pinto-otp.html</link><guid isPermaLink="true">http://codeofrob.com/entries/purerl-updates---maxing-out-pinto-otp.html</guid><dc:creator><![CDATA[Rob Ashton]]></dc:creator><pubDate>Thu, 21 Oct 2021 09:30:00 GMT</pubDate></item><item><title><![CDATA[Purerl Updates - Untagged Unions]]></title><description><![CDATA[<p>Yes, another blog post about Purerl, following on from</p>
<ul>
<li><a href="/entries/purerl-updates---processes-and-self.html">Purerl Updates - Processes and Self</a></li>
<li><a href="/entries/purerl-updates---subscriptions.html">Purerl Updates - Subscriptions</a></li>
</ul>
<p>We are now here to talk about untagged unions and how they can be used when dealing with legacy messages being sent to our process and why we might want to do something differently at all.</p>
<p>Consider a dependency to a legacy Erlang library that has a subscribe call that sends us messages</p>
<pre><code class="language-erlang">legacy_api:subscribe(),

<span class="hljs-keyword">receive</span> 
  { data, Bin } -&gt; ..
  { err, Reason } -&gt; ..
  eof -&gt; ..
</code></pre>
<p>It isn&#39;t possible to subcribe to this in Purescript without doing <em>something</em> to unpack those Erlang types. We could have</p>
<pre><code class="language-haskell"><span class="hljs-title">workerLoop</span> :: <span class="hljs-type">ProcessM</span> <span class="hljs-type">Foreign</span> <span class="hljs-type">Unit</span>
<span class="hljs-title">workerLoop</span> = <span class="hljs-keyword">do</span>
  msg &lt;- receive
  <span class="hljs-keyword">case</span> (<span class="hljs-type">LegacyApi</span>.unpack msg) <span class="hljs-keyword">of</span> 
    <span class="hljs-type">Err</span> err -&gt; ...
    <span class="hljs-type">Data</span> bin -&gt; ...
    <span class="hljs-type">Fin</span> -&gt; ...

<span class="hljs-title">startWorker</span> :: <span class="hljs-type">ProcessM</span> <span class="hljs-type">Foreign</span> <span class="hljs-type">Unit</span>
<span class="hljs-title">startWorker</span> = <span class="hljs-keyword">do</span>
  <span class="hljs-type">LegacyApi</span>.subscribe
  workerLoop
</code></pre>
<p>Simply leaving it to the caller to know that the Foreign needs running through the API again in order to decipher it.</p>
<p>We could also use the MessageRouter in Pinto to spin up another process that knows how to do this for us so this translation is already done once we&#39;re in user code</p>
<pre><code class="language-haskell"><span class="hljs-keyword">import</span> Pinto.MessageRouter <span class="hljs-keyword">as</span> MR

<span class="hljs-title">workerLoop</span> :: <span class="hljs-type">ProcessM</span> <span class="hljs-type">LegacyApi</span>.<span class="hljs-type">Msg</span> <span class="hljs-type">Unit</span>
<span class="hljs-title">workerLoop</span> = <span class="hljs-keyword">do</span>
  msg &lt;- receive
  <span class="hljs-keyword">case</span> msg <span class="hljs-keyword">of</span> 
    <span class="hljs-type">Err</span> err -&gt; ...
    <span class="hljs-type">Data</span> bin -&gt; ...
    <span class="hljs-type">Fin</span> -&gt; ...

<span class="hljs-title">startWorker</span> :: <span class="hljs-type">ProcessM</span> <span class="hljs-type">LegacyApi</span>.<span class="hljs-type">Msg</span> <span class="hljs-type">Unit</span>
<span class="hljs-title">startWorker</span> = <span class="hljs-keyword">do</span>
  me &lt;- self
  <span class="hljs-type">MR</span>.startRouter <span class="hljs-type">LegacyApi</span>.subscribe <span class="hljs-type">LegacyApi</span>.unsubscribe (self self &lt;&lt;&lt; <span class="hljs-type">LegacyApi</span>.unpack)
  workerLoop</code></pre>
<p>This is a viable solution for <em>most</em> scenarios because it is easy to understand, reasonably lightweight, allows us to accept more than one kind of message, etc. It incur the &quot;cost&quot; of spinning up another process, and it does incur the cost of doubling the number of messages being sent for a single interaction.</p>
<p>Usually this isn&#39;t a problem (or more - if doubling the messages or processes is going to cause you issues, then it&#39;s possible that the codebase already has issues anyway!). </p>
<p>Having said all of that, for FFI around existing Erlang where there are there are numerous variants, writing mapping code in Erlang could be rather error prone (and passing in constructors from Purescript gets tiresome after half a dozen) - it starts to make sense to instead try to describe the data types &quot;in place&quot; in Purescript using something formal.</p>
<p>For this, there is the package <a href="https://github.com/id3as/purescript-erl-untagged-union">purescript-untagged-union</a>.</p>
<p>Now, two of these values are directly representable in Purescript because of the way in which types are represented in Erlang under the hood.</p>
<pre><code class="language-haskell"><span class="hljs-class"><span class="hljs-keyword">data</span> <span class="hljs-type">LegacyMsg</span> </span>
  = <span class="hljs-type">Err</span> <span class="hljs-type">Binary</span>
  | <span class="hljs-type">Data</span> <span class="hljs-type">Binary</span></code></pre>
<p>We can let the untagged unions library know that underlying data maps onto this with an instance of RuntimeType that describes it</p>
<pre><code class="language-haskell">instance legacyMsg_runtimeType ::
  RuntimeType
    LegacyMsg
    (RTOption (RTTuple2 (RTLiteralAtom &quot;err&quot;) RTBinary)
               RTTuple2 (RTLiteralAtom &quot;data&quot; RTBinary))</code></pre>
<p>Come to think of it, that &#39;err&#39; is horrible, we&#39;re in Purescript and there is no reason to have such an ugly constructor - how about renaming it during mapping?</p>
<pre><code class="language-haskell">data LegacyMsg 
  = Error Binary
  | Data Binary

instance legacyMsg_runtimeType ::
  RuntimeType
    LegacyMsg
    (RTOption (RTTuple2 (RTLiteralAtomConvert &quot;err&quot; &quot;error&quot;) RTBinary)
               RTTuple2 (RTLiteralAtom &quot;data&quot; RTBinary))</code></pre>
<p>We still have that atom all by itself however, the atom &#39;fin&#39; isn&#39;t representable as a Purescript type, it is only an Atom but we&#39;d like still like to be able to receive it! </p>
<p>Well, we can build a type that represents our incoming messages, including that atom.</p>
<pre><code class="language-haskell"><span class="hljs-class"><span class="hljs-keyword">type</span> <span class="hljs-type">Msg</span> = <span class="hljs-type">Union</span> |$| <span class="hljs-type">AtomSymbol</span>.<span class="hljs-type">Atom</span> &quot;fin&quot; |+| <span class="hljs-type">LegacyMsg</span> |+| <span class="hljs-type">Nil</span></span></code></pre>
<p>And then all that is left is to use this in a process that can receive these messages</p>
<pre><code class="language-haskell"><span class="hljs-title">workerLoop</span> :: <span class="hljs-type">ProcessM</span> <span class="hljs-type">LegacyApi</span>.<span class="hljs-type">Msg</span> <span class="hljs-type">Unit</span>
<span class="hljs-title">workerLoop</span> = <span class="hljs-keyword">do</span>
  msg &lt;- receive
  ( case_ 
      # on (\(m&#x27; :: <span class="hljs-type">LegacyMsg</span>) -&gt;
          <span class="hljs-keyword">case</span> m&#x27; <span class="hljs-keyword">of</span> 
            <span class="hljs-type">Err</span> err -&gt; ...
            <span class="hljs-type">Data</span> bin -&gt; ...
        )
      # on (\(_ :: <span class="hljs-type">AtomSymbol</span>.<span class="hljs-type">Atom</span> <span class="hljs-string">&quot;fin&quot;</span>) -&gt;
            ...
        )
  ) msg

<span class="hljs-title">startWorker</span> :: <span class="hljs-type">ProcessM</span> <span class="hljs-type">LegacyApi</span>.<span class="hljs-type">Msg</span> <span class="hljs-type">Unit</span>
<span class="hljs-title">startWorker</span> = <span class="hljs-keyword">do</span>
  <span class="hljs-type">LegacyApi</span>.subscribe 
  workerLoop</code></pre>
<p>This needs to be exhaustive or we will get a compile error which is super cool. </p>
<p>All of this works without an additional process or a fumbly mapping layer. It&#39;s not perfect and relies on actually getting the type description correct but this at least presents a way of doing it without writing error-prone Erlang, which can be useful when dealing with APIs that have a whole array of random structures.</p>
]]></description><link>http://codeofrob.com/entries/purerl-updates---untagged-unions.html</link><guid isPermaLink="true">http://codeofrob.com/entries/purerl-updates---untagged-unions.html</guid><dc:creator><![CDATA[Rob Ashton]]></dc:creator><pubDate>Tue, 19 Oct 2021 09:30:00 GMT</pubDate></item><item><title><![CDATA[Purerl Updates - Subscriptions]]></title><description><![CDATA[<p>Two blog posts in a week? Unheard of - following on from Tuesday&#39;s blockbuster smash hit epic &quot;<a href="/entries/purerl-updates---processes-and-self.html">Purerl Updates - Processes and Self</a>&quot;, today we have an entry describing our current thoughts on subscriptions in a Purerl world.</p>
<p>A standard procedure in Erlang, is to invoke an API that then proceeds to send messages back to the invoking process.</p>
<pre><code class="language-erlang">some_api:subscribe()

<span class="hljs-keyword">receive</span> 
  Msg -&gt; ..</code></pre>
<p>More often or not, an overload will be provided allowing a Pid to be passed in, in case you didn&#39;t want it sending to <em>self</em>.</p>
<pre><code class="language-erlang">Pid = spawn_worker(),
some_api:subscribe(Pid)</code></pre>
<p>We could write a function that looks like this in Purescript (using the typeclasses explored in the previous blog entry).</p>
<pre><code class="language-haskell"><span class="hljs-keyword">module</span> SomeApi <span class="hljs-keyword">where</span>

<span class="hljs-class"><span class="hljs-keyword">data</span> <span class="hljs-type">Msg</span> = <span class="hljs-type">HelloWorld</span> | <span class="hljs-type">Goodbye</span></span>

<span class="hljs-title">subscribe</span> :: <span class="hljs-keyword">forall</span> process. 
  <span class="hljs-type">HasProcess</span> <span class="hljs-type">Msg</span> process =&gt; 
  process -&gt; <span class="hljs-type">Effect</span> <span class="hljs-type">Unit</span>
<span class="hljs-title">subscribe</span> = ...
</code></pre>
<p>In this, we are saying &quot;Given a process that accepts <em>Msg</em>, then the subscription will send <em>msg</em> to you.</p>
<pre><code class="language-haskell"><span class="hljs-title">workerLoop</span> :: <span class="hljs-type">ProcessM</span> <span class="hljs-type">SomeApi</span>.<span class="hljs-type">Msg</span> <span class="hljs-type">Unit</span>
<span class="hljs-title">workerLoop</span> = <span class="hljs-keyword">do</span>
  msg &lt;- receive
  <span class="hljs-keyword">case</span> msg <span class="hljs-keyword">of</span> 
    <span class="hljs-type">HelloWorld</span> -&gt; ...
    <span class="hljs-type">Goodbye</span> -&gt; ...

<span class="hljs-title">main</span> :: <span class="hljs-type">Effect</span> <span class="hljs-type">Unit</span>
<span class="hljs-title">main</span> = <span class="hljs-keyword">do</span> 
  process &lt;- spawnLink workerLoop
  <span class="hljs-type">SomeApi</span>.subscribe process</code></pre>
<p>This isn&#39;t great, typically we don&#39;t write processes this way - processes usually not only want to subscribe to messages from external sources, but also send themselves messages, typically they&#39;ll achieve that by lifting messages into a process specific data type.</p>
<pre><code class="language-haskell"><span class="hljs-class"><span class="hljs-keyword">data</span> <span class="hljs-type">ProcessMsg</span> </span>
  = <span class="hljs-type">ApiMsg</span> <span class="hljs-type">SomeApi</span>.<span class="hljs-type">Msg</span>
  | <span class="hljs-type">Tick</span>

<span class="hljs-title">workerLoop</span> :: <span class="hljs-type">ProcessM</span> <span class="hljs-type">ProcessMsg</span> <span class="hljs-type">Unit</span>
<span class="hljs-title">workerLoop</span> = ...
</code></pre>
<p>Calling <em>SomeApi.subscribe</em> with this process will result in a compiler error because SomeApi.Msg is the wrong type.</p>
<h2 id="emitters">Emitters</h2>
<p>The pattern we&#39;ve been using up until now to side-step this is for subscription calls to take in a blank cheque in the form of <em>msg -&gt; Effect Unit</em>, allowing the caller to decide what to do with messages on that subscription.</p>
<pre><code class="language-haskell"><span class="hljs-keyword">module</span> SomeApi <span class="hljs-keyword">where</span>

<span class="hljs-class"><span class="hljs-keyword">data</span> <span class="hljs-type">Msg</span> = <span class="hljs-type">HelloWorld</span> | <span class="hljs-type">Goodbye</span></span>

<span class="hljs-title">subscribe</span> :: (<span class="hljs-type">Msg</span> -&gt; <span class="hljs-type">Effect</span> <span class="hljs-type">Unit</span>) -&gt; <span class="hljs-type">Effect</span> <span class="hljs-type">Unit</span>
<span class="hljs-title">subscribe</span> = ...
</code></pre>
<p>Subscription could then look like this</p>
<pre><code class="language-haskell"><span class="hljs-class"><span class="hljs-keyword">data</span> <span class="hljs-type">ProcessMsg</span> </span>
  = <span class="hljs-type">ApiMsg</span> <span class="hljs-type">SomeApi</span>.<span class="hljs-type">Msg</span>
  | <span class="hljs-type">Tick</span>

<span class="hljs-title">main</span> :: <span class="hljs-type">Effect</span> <span class="hljs-type">Unit</span>
<span class="hljs-title">main</span> = <span class="hljs-keyword">do</span> 
  process &lt;- spawnLink workerLoop
  <span class="hljs-type">SomeApi</span>.subscribe $ send process &lt;&lt;&lt; <span class="hljs-type">ApiMsg</span></code></pre>
<p>More commonly the use of some form of <em>self</em> would be used inside the process itself, as it makes little sense for one process to subscribe on behalf of another.</p>
<pre><code class="language-haskell"><span class="hljs-title">workerLoop</span> :: <span class="hljs-type">ProcessM</span> <span class="hljs-type">SomeApi</span>.<span class="hljs-type">Msg</span> <span class="hljs-type">Unit</span>
<span class="hljs-title">workerLoop</span> = <span class="hljs-keyword">do</span>
  msg &lt;- receive
  <span class="hljs-keyword">case</span> msg <span class="hljs-keyword">of</span> 
    <span class="hljs-type">HelloWorld</span> -&gt; ...
    <span class="hljs-type">Goodbye</span> -&gt; ...

<span class="hljs-title">startWorker</span> :: <span class="hljs-type">ProcessM</span> <span class="hljs-type">SomeApi</span>.<span class="hljs-type">Msg</span> <span class="hljs-type">Unit</span>
<span class="hljs-title">startWorker</span> = <span class="hljs-keyword">do</span>
  me &lt;- self
  liftEffect $ <span class="hljs-type">SomeApi</span>.subscribe $ send me &lt;&lt;&lt; <span class="hljs-type">ApiMsg</span>
  workerLoop

<span class="hljs-title">main</span> :: <span class="hljs-type">Effect</span> <span class="hljs-type">Unit</span>
<span class="hljs-title">main</span> = <span class="hljs-keyword">do</span> 
  _ &lt;- spawnLink workerLoop
</code></pre>
<p>This <em>works</em> and is elegant - and indeed for about two years this has been The Way. Our codebase is/was littered with <em>send me &lt;&lt;&lt; Msg</em>, but in hindsight this isn&#39;t great.</p>
<p>Why not? The problem with <em>Effect Unit</em> is that it can do anything. <em>ANYTHING</em>. The problem with passing an <em>Effect Unit</em> is that it can do that &quot;anything&quot; within the context of a completely different process. This can cause problems.</p>
<p><em>Errors</em>: What happens if the Effect Unit causes an exception? Who crashes? The remote process? Who does that affect? Anybody else who is currently subscribed? How do they find out? Are they in the right supervision tree for this not to be a problem? Can we just swallow the exception? How does the caller find out that it crashed? Oh dear.</p>
<p><em>Interference</em>: What if this is in a message loop doing other things? What if the <em>Effect Unit</em> takes up precious time? What happens to the backlog? What happens to anything awaiting a message with a timeout? </p>
<p>While the reality is that while nearly all our callbacks are implemented as <em>send me &lt;&lt;&lt; Msg</em>, as our codebases grow and we do more and more of these things, somebody is eventually going to cause problems with the above and we&#39;ll be looking at hilarious (and needless) debug sessions as a result. If not us - then somebody else using Purerl (and our numbers <em>are</em> growing...).</p>
<h2 id="hasself-to-the-rescue">HasSelf to the rescue</h2>
<p>HasSelf was added fairly recently and makes it possible to write code that operates inside any monad provided it has an implementation of &#39;self&#39;.</p>
<pre><code class="language-haskell"><span class="hljs-title">saferSubscribe</span> ::
  <span class="hljs-keyword">forall</span> m msg.
  <span class="hljs-type">MonadEffect</span> m =&gt;
  <span class="hljs-type">HasSelf</span> m msg =&gt;
  (<span class="hljs-type">Msg</span> -&gt; msg) -&gt; m <span class="hljs-type">Unit</span>
<span class="hljs-title">saferSubscribe</span> f = <span class="hljs-keyword">do</span>
  me :: (<span class="hljs-type">Process</span> msg) &lt;- self
  liftEffect $ subscribe $ send me &lt;&lt;&lt; f
  pure unit</code></pre>
<p>Adding onto that, we need to assert that we can evaluate effects in this monad (MonadEffect m =&gt;) in order to actually issue the subscription and suddenly our call to this becomes</p>
<pre><code class="language-haskell"><span class="hljs-title">workerLoop</span> :: <span class="hljs-type">ProcessM</span> <span class="hljs-type">SomeApi</span>.<span class="hljs-type">Msg</span> <span class="hljs-type">Unit</span>
<span class="hljs-title">workerLoop</span> = <span class="hljs-keyword">do</span>
  msg &lt;- receive
  <span class="hljs-keyword">case</span> msg <span class="hljs-keyword">of</span> 
    <span class="hljs-type">HelloWorld</span> -&gt; ...
    <span class="hljs-type">Goodbye</span> -&gt; ...

<span class="hljs-title">startWorker</span> :: <span class="hljs-type">ProcessM</span> <span class="hljs-type">SomeApi</span>.<span class="hljs-type">Msg</span> <span class="hljs-type">Unit</span>
<span class="hljs-title">startWorker</span> = <span class="hljs-keyword">do</span>
  <span class="hljs-type">SomeApi</span>.saferSubscribe <span class="hljs-type">ApiMsg</span>
  workerLoop

<span class="hljs-title">main</span> :: <span class="hljs-type">Effect</span> <span class="hljs-type">Unit</span>
<span class="hljs-title">main</span> = <span class="hljs-keyword">do</span> 
  _ &lt;- spawnLink workerLoop
</code></pre>
<p>Note: The liftEffect is gone, as is the call to &#39;self&#39;, the API looks a <em>lot</em> more like the original Erlang and is safer while we&#39;re at it. </p>
<p>Because it&#39;s no longer a blank cheque, we should probably provide a second method (just like in Erlang) that takes a process to send messages to instead of simply relying on &#39;self&#39;.</p>
<pre><code class="language-haskell"><span class="hljs-title">saferSubscribeTo</span> ::
  <span class="hljs-keyword">forall</span> msg.
  <span class="hljs-type">Process</span> msg -&gt; (<span class="hljs-type">Msg</span> -&gt; msg) -&gt; <span class="hljs-type">Effect</span> <span class="hljs-type">Unit</span>
<span class="hljs-title">saferSubscribeTo</span> p f = <span class="hljs-keyword">do</span> subscribe $ send p &lt;&lt;&lt; f</code></pre>
<p>This is how most of our subscriptions now look across Pinto/our own code/etc. It&#39;s safer for everybody concerned and fits well with the ethos of &#39;trying to look like the Erlang APIs most of this stuff is built on top of&#39;.</p>
]]></description><link>http://codeofrob.com/entries/purerl-updates---subscriptions.html</link><guid isPermaLink="true">http://codeofrob.com/entries/purerl-updates---subscriptions.html</guid><dc:creator><![CDATA[Rob Ashton]]></dc:creator><pubDate>Thu, 14 Oct 2021 09:30:00 GMT</pubDate></item><item><title><![CDATA[Purerl Updates - Processes and Self]]></title><description><![CDATA[<p>It has been about three years since I first sat in a hotel in Lithuania throwing together the first versions of <a href="https://github.com/id3as/purescript-erl-pinto">purescript-erl-pinto</a> and <a href="https://github.com/id3as/purescript-erl-stetson">purescript-erl-stetson</a> so that we could get started on a project for one of our clients.</p>
<p>Quite a lot of code has been written against those projects internally by colleagues and myself and over time:</p>
<ul>
<li>Various improvements/patterns have been discovered within core libraries such as <a href="https://github.com/purerl/purescript-erl-process">purescript-erl-process</a>. </li>
<li>A heap of Erlang specific packages have been written and released</li>
<li>Another mountain of packages have been ported across from Purescript </li>
<li>Pinto and Stetson have been upgraded repeatedly by various colleagues as our understanding of what we need them to do has evolved.</li>
</ul>
<p>The <a href="https://purerl-cookbook.readthedocs.io/">purerl cookbook</a> has been updated for these latest releases, as has the <a href="https://github.com/id3as/demo-ps">demo-ps</a> but felt it worthwhile highlighting some of the changes in a few (of my increasingly rare) blog posts.</p>
<p>In this post we&#39;ll be looking at Processes and the concept of &#39;self&#39;</p>
<h1 id="processes">Processes</h1>
<p>A common practise in Erlang codebases is to spawn a new process and use its Pid for communication.</p>
<pre><code class="language-erlang"><span class="hljs-function"><span class="hljs-title">example</span><span class="hljs-params">()</span> -&gt;</span>
  Pid = spawn_link(fun receive_message/0)
  Pid ! hi.

<span class="hljs-function"><span class="hljs-title">receive_message</span><span class="hljs-params">()</span> -&gt;</span>
  <span class="hljs-keyword">receive</span>
    SomeMessage -&gt; 
      ?PRINT(<span class="hljs-string">&quot;Got a message&quot;</span>),
      ok
   <span class="hljs-keyword">end</span>.</code></pre>
<p>In Purerl, the type <em>Pid</em> lives in <em>Erl.Process.Raw</em> and is just an imported foreign type</p>
<pre><code class="language-haskell"><span class="hljs-keyword">foreign</span> <span class="hljs-keyword">import</span> data <span class="hljs-type">Pid</span> :: <span class="hljs-type">Type</span></code></pre>
<p>This typically isn&#39;t used to any great amount except in some specific FFI cases, it being far better generally to use the types found in <em>Erl.Process</em> which have the phantom type <em>msg</em> floating around meaning all the sends and receives are limited to the types of message that that process has declared it will receive. <em>Process msg</em> itself is just a newtype around Raw.Pid of course.</p>
<pre><code class="language-haskell"><span class="hljs-class"><span class="hljs-keyword">newtype</span> <span class="hljs-type">Process</span> (<span class="hljs-title">a</span> :: <span class="hljs-type">Type</span>)</span>
  = <span class="hljs-type">Process</span> <span class="hljs-type">Raw</span>.<span class="hljs-type">Pid</span></code></pre>
<p>To create a typed process, one could call <em>spawnLink</em> and provide a callback which will be executed in the process created in that underlying call to <em>spawn_link</em> in Erlang. A change made fairly early on in development was to change this callback from something that took some context, to something that operated inside <em>ProcessM msg r</em>, with the context being provided by that monad - this will become important later on in this blog entry so I&#39;ll demonstrate this here.</p>
<h2 id="the-old-way">The old way</h2>
<p>&quot;Given a callback that accepts a <em>SpawnLinkContext</em> typed around <em>msg</em>, run that callback inside a new process and return that new process, also typed around <em>msg</em>&quot;</p>
<pre><code class="language-haskell"><span class="hljs-title">spawnLink</span> :: <span class="hljs-keyword">forall</span> msg. (<span class="hljs-type">SpawnLinkContext</span> msg -&gt; <span class="hljs-type">Effect</span> <span class="hljs-type">Unit</span>) -&gt; <span class="hljs-type">Effect</span> (<span class="hljs-type">Process</span> msg)</code></pre>
<p>That context then provided the means of receiving messages, being defined as something like</p>
<pre><code class="language-haskell"><span class="hljs-class"><span class="hljs-keyword">type</span> <span class="hljs-type">SpawnLinkContext</span> msg = </span>
  { receive :: <span class="hljs-type">Effect</span> msg 
  , receiveWithTimeout :: <span class="hljs-type">Timeout</span> -&gt; <span class="hljs-type">Effect</span> (<span class="hljs-type">Maybe</span> msg)
  }</code></pre>
<p>Thus, the Erlang example, re-written in Purerl would have looked something like this</p>
<pre><code class="language-haskell"><span class="hljs-title">example</span> :: <span class="hljs-type">Effect</span> <span class="hljs-type">Unit</span>
<span class="hljs-title">example</span> = <span class="hljs-keyword">do</span>
  pid &lt;- spawnLink receiveMessage
  pid ! <span class="hljs-string">&quot;hi&quot;</span>

<span class="hljs-title">receiveMessage</span> :: <span class="hljs-type">SpawnLinkContext</span> <span class="hljs-type">String</span> -&gt; <span class="hljs-type">Effect</span> <span class="hljs-type">Unit</span>
<span class="hljs-title">receiveMessage</span> c = <span class="hljs-keyword">do</span> 
  msg &lt;- c.receive
  log <span class="hljs-string">&quot;Got a message&quot;</span></code></pre>
<h2 id="the-new-way">The new way</h2>
<p>&quot;Evaluate the given code in the context of a <em>ProcessM</em> typed around <em>msg</em>&quot;</p>
<pre><code class="language-haskell"><span class="hljs-title">spawnLink</span> :: <span class="hljs-keyword">forall</span> msg. <span class="hljs-type">ProcessM</span> msg <span class="hljs-type">Unit</span> -&gt; <span class="hljs-type">Effect</span> (<span class="hljs-type">Process</span> msg)</code></pre>
<p>And quite simply, any calls to receive/etc are defined as functions that operate inside ProcessM, again all typed around <em>msg</em></p>
<pre><code class="language-haskell"><span class="hljs-title">receive</span> :: <span class="hljs-keyword">forall</span> msg. <span class="hljs-type">ProcessM</span> msg msg
<span class="hljs-title">receive</span> = <span class="hljs-type">ProcessM</span> <span class="hljs-type">Raw</span>.receive</code></pre>
<p>This cuts down on the cruft somewhat, as instead of having to pass a context everywhere, one can simply write functions in the context of ProcessM, re-writing that initial example now looks like this (Note that the log call needs lifting into <em>ProcessM</em> because it is written as an <em>Effect</em>)</p>
<pre><code class="language-haskell"><span class="hljs-title">example</span> :: <span class="hljs-type">Effect</span> <span class="hljs-type">Unit</span>
<span class="hljs-title">example</span> = <span class="hljs-keyword">do</span>
  pid &lt;- spawnLink receiveMessage
  pid ! <span class="hljs-string">&quot;hi&quot;</span>

<span class="hljs-title">receiveMessage</span> :: <span class="hljs-type">ProcessM</span> <span class="hljs-type">String</span> <span class="hljs-type">Unit</span>
<span class="hljs-title">receiveMessage</span> = <span class="hljs-keyword">do</span> 
  msg &lt;- receive
  liftEffect $ log <span class="hljs-string">&quot;Got a message&quot;</span></code></pre>
<h2 id="extending-this-model">Extending this model</h2>
<p>It turns out that this is quite a nice pattern for representing the different <em>types</em> of process available in Erlang (OTP, Cowboy and indeed our own application code), consider:</p>
<ul>
<li>Cowboy Loop handlers</li>
<li>Cowboy Websocket handlers</li>
<li>OTP gen_server</li>
<li>OTP supervisor</li>
<li>OTP gen_statem</li>
</ul>
<p>All of these could be ran as <em>ProcessM</em>, except they have more types associated with them <em>and</em> various functions available designed for use in those specific contexts, for example in the simple case of cowboy..</p>
<pre><code class="language-haskell"><span class="hljs-class"><span class="hljs-keyword">type</span> <span class="hljs-type">WebSocketInfoHandler</span> msg state</span>
  = msg -&gt; state -&gt; <span class="hljs-type">WebSocketResult</span> msg (<span class="hljs-type">WebSocketCallResult</span> state)</code></pre>
<p>We have the types <em>msg</em> and <em>state</em> in our type because the callbacks involved tend to take <em>state</em> and there is a callback (<em>info</em>) for messages received by the loop handler typed around <em>msg</em></p>
<p>In the more complicated case of an OTP GenServer, this looks like this</p>
<pre><code>type C<span class="hljs-literal">all</span>Fn reply cont stop msg <span class="hljs-keyword">state</span>
  = From reply -&gt; <span class="hljs-keyword">state</span> -&gt; ResultT cont stop msg <span class="hljs-keyword">state</span> (C<span class="hljs-literal">all</span>Result reply cont stop <span class="hljs-keyword">state</span>)</code></pre><p>Most operations take place inside that <em>ResultT</em> which encodes the <em>cont</em>, <em>stop</em>, <em>msg</em>, and <em>state</em> types for use with our operations. (<em>cont</em> being the message that can be received by <em>handle_continue</em>, <em>stop</em> being a custom stop reason, <em>msg</em> being messages received by <em>handle_info</em> and <em>state</em> being the state of the gen server).</p>
<p>We also end up with our own contexts in our own codebases for specific process types around common units of business logic. </p>
<h2 id="common-functionality">Common Functionality</h2>
<p>In most of these cases, just like with <em>Process.spawnLink</em>, something gets returned that represents the started process - for example the GenServer.</p>
<pre><code class="language-haskell"><span class="hljs-title">startLink</span> :: <span class="hljs-keyword">forall</span> cont stop msg state. 
  (<span class="hljs-type">ServerSpec</span> cont stop msg state) 
  -&gt; <span class="hljs-type">Effect</span> (<span class="hljs-type">StartLinkResult</span> (<span class="hljs-type">ServerPid</span> cont stop msg state))</code></pre>
<p>Here we have a <em>ServerPid cont stop msg state</em> returned to the caller - again keeping a lot of useful information around to help us make calls into a GenServer but the type we&#39;re interested in here is <em>msg</em>. Most generic APIs will be written around the concept of a <em>Process msg</em> and what we have here is a <em>ServerPid cont stop msg state</em></p>
<p>The logical step here is to expose</p>
<pre><code class="language-haskell"><span class="hljs-title">toProcess</span> :: <span class="hljs-type">ServerPid</span> cont stop msg state -&gt; <span class="hljs-type">Process</span> msg</code></pre>
<p>It turns out that this is a very common operation and so a typeclass is born and added to Erl.Process for everybody to implement when writing this kind of code.</p>
<pre><code class="language-haskell"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-type">HasProcess</span> b a <span class="hljs-keyword">where</span></span>
  getProcess :: a -&gt; <span class="hljs-type">Process</span> b</code></pre>
<p>In fact, two typeclasses are born because some APIs only need a Pid after all.</p>
<pre><code class="language-haskell"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-type">HasPid</span> a <span class="hljs-keyword">where</span></span>
  getPid :: a -&gt; <span class="hljs-type">Pid</span></code></pre>
<p>Most functions that take a <em>Process msg</em> therefore don&#39;t actually care about it <em>being</em> a <em>Process msg</em>, but only that a <em>Process msg</em> can be gotten from the type</p>
<pre><code class="language-haskell"><span class="hljs-title">callMe</span> :: <span class="hljs-keyword">forall</span> p msg. 
  <span class="hljs-type">HasProcess</span> msg p =&gt; 
  p -&gt; <span class="hljs-type">Effect</span> <span class="hljs-type">Unit</span></code></pre>
<p>And now all of those custom types can be used with a whole suite of APIs without having to unpack a convoluted structure of newtypes.</p>
<h2 id="self">Self</h2>
<p>There is one more common operation that has been ignored so far, and that is the concept of self. An incredibly common thing in Erlang is to invoke <em>self</em> to get the Pid of the current process.</p>
<pre><code class="language-erlang">Self = self(),
some_api:call_me(Self)</code></pre>
<p>For a while, we started having <em>self</em> methods on every module that exported some monad in which process logic could be evalulated, and this would return the full type of the process (complete with <em>cont</em>, <em>stop</em>, <em>state</em>, etc). There were a lot of <em>self</em> functions being exported and imported and in 99.99% of all cases they were immediately followed by a call to <em>getProcess</em> using the <em>HasProcess</em> typeclass implementation for that system.</p>
<pre><code class="language-haskell">(me :: <span class="hljs-type">Process</span> <span class="hljs-type">MyMsg</span>) &lt;- getProcess &lt;$&gt; <span class="hljs-type">GenServer</span>.self</code></pre>
<p>What does <em>self</em> mean then? The correct answer is as written above, but the correct answer isn&#39;t always the nicest answer - it was very rare that we would need anything from <em>self</em> other than the current <em>Process msg</em> and we were running into issues in modules that had code for more than one of these contexts in them, whose self are we using anyway?</p>
<p>The answer was to be pragmatic and create a typeclass for &#39;<em>any m</em>&#39; that allowed that &#39;<em>m</em>&#39; to export a <em>Process msg</em></p>
<pre><code class="language-haskell"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-type">HasSelf</span> (<span class="hljs-title">m</span> :: <span class="hljs-type">Type</span> -&gt; <span class="hljs-type">Type</span>) msg | m -&gt; msg <span class="hljs-keyword">where</span></span>
  self :: m (<span class="hljs-type">Process</span> msg)</code></pre>
<p>For the case of anything running inside a <em>ProcessM</em>, this isn&#39;t any more complicated than calling Raw.self to get the current pid and wrapping it up with the relevant newtypes</p>
<pre><code class="language-haskell"><span class="hljs-class"><span class="hljs-keyword">instance</span> selfProcessM :: <span class="hljs-type">HasSelf</span> (<span class="hljs-type">ProcessM</span> <span class="hljs-title">a</span>) a <span class="hljs-keyword">where</span></span>
  self :: <span class="hljs-keyword">forall</span> a. <span class="hljs-type">ProcessM</span> a (<span class="hljs-type">Process</span> a)
  self = <span class="hljs-type">ProcessM</span> $ <span class="hljs-type">Process</span> &lt;$&gt; <span class="hljs-type">Raw</span>.self</code></pre>
<p>Similar implementations then exist for Pinto/Stetson contexts, allowing code to simply call <em>Process.self</em> from practically anywhere to get a typed <em>Process msg</em> valid for the current context.</p>
<pre><code class="language-haskell"><span class="hljs-type">SomeApi</span>.callMe &lt;&lt;&lt; self</code></pre>
<p>All typed, all safe, nobody sent messages they can&#39;t handle - living the dream.</p>
]]></description><link>http://codeofrob.com/entries/purerl-updates---processes-and-self.html</link><guid isPermaLink="true">http://codeofrob.com/entries/purerl-updates---processes-and-self.html</guid><dc:creator><![CDATA[Rob Ashton]]></dc:creator><pubDate>Tue, 12 Oct 2021 09:30:00 GMT</pubDate></item><item><title><![CDATA[Write Your Erlang Gen Servers in Visual Basic]]></title><description><![CDATA[<p>TLDR: <a href="https://github.com/robashton/erlang.net">Erlang.NET Released on Github</a></p>
<p>I&#39;ve been working in Erlang now for nearly a decade and for the last year or two we have been investigating what it would take to start writing a <em>lot</em> more of that Erlang in Purescript instead because in theory working in a sensibly typed language means fewer bugs means fewer support calls means more time spent working on features which can be sold and therefore this is good for profit margins.</p>
<p>Well let me tell you - it blows, we have lost weeks trying to write typeclasses around row types to confirm that &#39;this chunk of binary is good to go into this piece of code that just wants a chunk of binary&#39; and months pontificating over whether an attribute should be declared at the type-level or merely at runtime and whilst progress has been made, it has been a slow and painful exercise.</p>
<p><em>There has to be a better way</em></p>
<p>I worked with one of my colleagues in a previous job many years ago - it was an honest living. We wrote VB.NET together in the heyday of .NETs 1 and 2 and by golly we were very productive indeed. It has types but it also has freedom, It has generics but it also reads really cleanly because so much of its syntax is just <em>words</em> - in other words it is almost the perfect language for writing expressive code. Since departing the world of dotnet however I have noticed its younger brother, C#, appearing in environments like Unity and other game engines as a scripting utility and that got me thinking - what if we could use host .NET in a similar way and use C# as a <em>real</em> language and build real software with it instead? (Leaving us to use VB.NET at our leisure whilst appealing to the masses that prefer C#). </p>
<p><em>Catching up with dotnet</em></p>
<p>It has been a while since I touched base with dotnet, probably again about a decade. I largely quit because the default tooling was very mouse heavy and my wrists were starting to get sore (true story), not to mention most enterprise shops using the technology being <a href="/entries/why-you-cant-be-a-good-.net-developer.html">heavy with the derp</a>. (Some) things have apparently changed since then, tooling-wise everything seems to revolve around the <em>dotnet</em> CLI and with the language-server happenings being commonplace across most platforms, the support for writing .NET languages in Vim is not half bad out of the gate. Huzzah.</p>
<p>.NET Core 5.0.0 seemed the obvious candidate seeing as that seems to be a unification point for all the complicated versioning stories that Microsoft is so fond of creating. Version <em>5.0.0</em>, not just one zero - but two, that&#39;s how you know that software is ready for use!</p>
<p><em>The solution</em></p>
<p>We have a lot of legacy Erlang so if we&#39;re to start writing dotnet code to replace it we&#39;ll first need to find a way to interoperate - the <em>obvious</em> solution is to launch the dotnet code inside the existing Erlang Application side by side so they can talk to each other.</p>
<p>If we write the following app in dotnet (spin up a gen server and return the pid)</p>
<pre><code class="language-csharp">  <span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">MyEnterpriseGradeApp</span> : <span class="hljs-title">IApp</span> {
    <span class="hljs-function"><span class="hljs-keyword">public</span> Object <span class="hljs-title">Start</span>(<span class="hljs-params"></span>)</span> {
      <span class="hljs-keyword">return</span> GenServer.StartLink(() =&gt; <span class="hljs-keyword">new</span> MyCoolGenServer() );
    }
  }</code></pre>
<p>We can embed it in a standard Erlang Gen Supervisor like so:</p>
<pre><code class="language-erlang">
  init([]) -&gt;
    {ok, { #{ strategy =&gt; one_for_one }, 
           #{ start =&gt; { dotnet_shim
                       , start_link
                       , [ <span class="hljs-string">&quot;priv/acme.dll&quot;</span>, <span class="hljs-string">&quot;Acme.MyEnterpriseGradeApp&quot;</span> ]
                       }
            , id =&gt; acme_app
            , type =&gt; worker
            }
       ]}}.
</code></pre>
<p>And this <em>just works</em> - Those of you who know both Erlang and dotnet at this point will hopefully be picking your jaw back off the floor - what on earth is going on here?</p>
<p><em>The simplest example</em></p>
<p>At its heart, an <em>IApp</em> is simply a class that has a Start method that&#39;ll return <em>something</em> back up to Erlang, these can be launched manually from Erlang to execute arbitrary code - for example, here is an app written in dotnet that returns a fixed string to us...</p>
<pre><code class="language-csharp">  <span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">HelloApp</span> : <span class="hljs-title">IApp</span> {
    <span class="hljs-function"><span class="hljs-keyword">public</span> Object <span class="hljs-title">Start</span>(<span class="hljs-params"></span>)</span> {
      <span class="hljs-keyword">return</span> <span class="hljs-string">&quot;Hello Joe&quot;</span>;
    }
  }
</code></pre>
<p>Can be executed from Erlang like so</p>
<pre><code class="language-erlang">  { ok, Result } = dotnet:run_app_from_assembly(<span class="hljs-string">&quot;priv/acme.dll&quot;</span>, <span class="hljs-string">&quot;Acme.HelloApp&quot;</span>),
  ?LOG(Result). <span class="hljs-comment">%% Hello Joe</span></code></pre>
<p>You will notice that the result from dotnet was automatically wrapped in an <em>{ok, Result}</em> tuple, as most Erlang APIs will expect that, if our dotnet code throws an exception then this will be automatically returned back as an <em>{ error, Reason }</em> instead - this seemed to be the cleanest way of expressing error conditions (and a special Exception (<em>TermException</em>) class is provided for explicitly providing that Reason to the Erlang host.</p>
<p><em>Passing values in</em></p>
<p>A generic implementation of <em>IApp</em> exists, <em>IApp<TArgs></em>, for which an input can be requested by the <em>Start</em> method, for example adding two numbers together</p>
<pre><code class="language-csharp">  public class AddApp : IApp&lt;Tuple&lt;Int,Int&gt;&gt; {
    public Object Start((int x, int y)) {
      return x + y;
    }
  }
</code></pre>
<pre><code class="language-erlang">  { ok, Result } = dotnet:run_app_from_assembly(<span class="hljs-string">&quot;priv/acme.dll&quot;</span>, <span class="hljs-string">&quot;Acme.AddApp&quot;</span>, { <span class="hljs-number">5</span>, <span class="hljs-number">5</span> }),
  ?LOG(Result). <span class="hljs-comment">%% 10</span></code></pre>
<p>The observant reader will notice that we&#39;re using a dotnet <em>Tuple&lt;Int, Int&gt;</em> here and passing in an erlang tuple <em>{ integer(), integer }</em> and it just maps across automatically, how does this work? Ah well, go read the source code to find out or wait for the blog posts that I&#39;ll be writing on that subject, for now just accept that you can stick pretty much anything in your type signature and the equivalent Erlang types will get converted across. How about using a record instead of the tuple for example?</p>
<pre><code class="language-csharp">  <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">record</span> <span class="hljs-title">AddArgs</span> (<span class="hljs-params"><span class="hljs-built_in">int</span> X, <span class="hljs-built_in">int</span> Y</span>)</span>;

  <span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">AddApp</span> : <span class="hljs-title">IApp</span>&lt;<span class="hljs-title">AddArgs</span>&gt; {
    <span class="hljs-function"><span class="hljs-keyword">public</span> Object <span class="hljs-title">Start</span>(<span class="hljs-params">AddArgs args</span>)</span> {
      <span class="hljs-keyword">return</span> args.X + args.Y;
    }
  }
</code></pre>
<pre><code class="language-erlang">  { ok, Result } = dotnet:run_app_from_assembly(<span class="hljs-string">&quot;priv/acme.dll&quot;</span>, <span class="hljs-string">&quot;Acme.HelloApp&quot;</span>, #{ x =&gt; <span class="hljs-number">5</span>, y =&gt; <span class="hljs-number">5</span> }),
  ?LOG(Result). <span class="hljs-comment">%% 10</span></code></pre>
<p>Not a problem. The observant reader will notice that not only is the casing automatically adjusted (Erlang is typically <em>snake_case</em>, and dotnet is typically <em>PascalCase</em>) but return type of Start is just a plain ol&#39; object, and the same thing applies there, return anything you like and it&#39;ll get converted into something that Erlang will understand. Records on records? Not a problem.</p>
<pre><code class="language-csharp">
  <span class="hljs-keyword">public</span> <span class="hljs-keyword">record</span> <span class="hljs-title">ComplexReturnValue</span> {
    <span class="hljs-keyword">public</span> AnotherComplexValue Why { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">init</span>; }
    <span class="hljs-keyword">public</span> <span class="hljs-built_in">int</span> Y { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">init</span>; }
    <span class="hljs-keyword">public</span> String Rye { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">init</span>; }
  }

  <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">record</span> <span class="hljs-title">AnotherComplexValue</span> (<span class="hljs-params"> <span class="hljs-built_in">string</span> Because </span>)</span>;

  <span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">ComplexApp</span> : <span class="hljs-title">IApp</span> {
    <span class="hljs-function"><span class="hljs-keyword">public</span> Object <span class="hljs-title">Start</span>(<span class="hljs-params"></span>)</span> {
      <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> ComplexReturnValue {
        Why = <span class="hljs-keyword">new</span> () { 
          Because = <span class="hljs-string">&quot;We can&quot;</span>
        },
        Y = <span class="hljs-number">1337</span>,
        Rye = <span class="hljs-string">&quot;Rittenhouse&quot;</span>
      };
    }
  }</code></pre>
<pre><code class="language-erlang">  { ok, #{ why := #{ because := Reason }
         , y := Number
         , rye := Whisky
  }} = dotnet:run_app_from_assembly(<span class="hljs-string">&quot;priv/acme.dll&quot;</span>, <span class="hljs-string">&quot;Acme.ComplexApp&quot;</span>),

  <span class="hljs-comment">%% Why: &quot;We can&quot;, y: 1337, rye: &quot;Rittenhouse&quot;</span>
  ?LOG(<span class="hljs-string">&quot;Why: ~p, y: ~p, rye: ~p ~n&quot;</span>, [Reason, Number, Whisky ]). 
</code></pre>
<p><em>Back to that Dotnet GenServer then</em></p>
<p>We&#39;ve established that we can invoke arbitary dotnet code from Erlang, which is already probably one of the most useful things I&#39;ve created this year - the Erlang eco system is almost non-existent and being able to access all of that open source technology in Nuget is going to save us a lot of future development time. Going back to the start of this blog post our very first example was one of spinning up an actual genserver in dotnet - that is to say, code that is going to execute in its own Erlang process and in turn be able to execute its own arbitrary logic outside of the single function call that kicked that off.</p>
<p>That example again:</p>
<pre><code class="language-csharp">  <span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">MyEnterpriseGradeApp</span> : <span class="hljs-title">IApp</span> {
    <span class="hljs-function"><span class="hljs-keyword">public</span> Object <span class="hljs-title">Start</span>(<span class="hljs-params"></span>)</span> {
      <span class="hljs-keyword">return</span> GenServer.StartLink(() =&gt; <span class="hljs-keyword">new</span> MyCoolGenServer() );
    }
  }</code></pre>
<p>A standard gen server in Erlang would look something like this</p>
<pre><code class="language-erlang"><span class="hljs-function"><span class="hljs-title">start_link</span><span class="hljs-params">(Arg1, Arg2)</span> -&gt;</span>
  <span class="hljs-comment">%% Executed in host process</span>
  gen_server:start_link({local, ?MODULE}, [Arg1, Arg2]).

<span class="hljs-function"><span class="hljs-title">init</span><span class="hljs-params">([Arg1, Arg2])</span> -&gt;</span>
  <span class="hljs-comment">%% Executed in new gen process</span>
  #state { one = Arg1, two = Arg2 }</code></pre>
<p>In the dotnet above, initial StartLink call takes place in the host process, and the callback is what is invoked in the init call and is expected to return &#39;some state&#39;. At its simplest, that state could just be an empty object:</p>
<pre><code class="language-csharp">  <span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">MyCoolGenServer</span> {}</code></pre>
<p>In Erlang, if you want to invoke some code in the process that kicked off these shenanigans, you would invoke that code via a gen_server method (call/cast) or send a message via the pid using the bang (<em>!</em>) operator, and so long as the relevant callback was implemented that would result in something happening.</p>
<pre><code class="language-erlang"><span class="hljs-function"><span class="hljs-title">start_link</span><span class="hljs-params">()</span> -&gt;</span>
  gen_server:start_link({local, ?MODULE}, []).

<span class="hljs-function"><span class="hljs-title">init</span><span class="hljs-params">([])</span> -&gt;</span>
  #state{}

handle_info(Msg, State) -&gt;
  ?LOG(Msg),
  {noreply, State}.</code></pre>
<p>Used as thus</p>
<pre><code class="language-erlang">  { ok, Pid } = my_cool_genserver:start_link(),

  <span class="hljs-comment">%% Hello Robert</span>
  Pid ! <span class="hljs-string">&quot;Hello Robert&quot;</span>.
</code></pre>
<p>The same thing works in dotnet (woah), we just need to implement an interface on the object that gets returned in that init call</p>
<pre><code class="language-csharp"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">MyCoolGenServer</span> : <span class="hljs-title">IHandleInfo</span>&lt;<span class="hljs-title">String</span>&gt; {
  <span class="hljs-function"><span class="hljs-keyword">public</span> HandleInfoResult <span class="hljs-title">HandleInfo</span>(<span class="hljs-params">HandleInfoContext ctx, String msg</span>)</span> {
    Console.WriteLine(msg);
    <span class="hljs-keyword">return</span> ctx.NoReply();
  }
}

<span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">MyEnterpriseGradeApp</span> : <span class="hljs-title">IApp</span> {
  <span class="hljs-function"><span class="hljs-keyword">public</span> Object <span class="hljs-title">Start</span>(<span class="hljs-params"></span>)</span> { 
    <span class="hljs-keyword">return</span> GenServer.StartLink(() =&gt; <span class="hljs-keyword">new</span> MyCoolGenServer());
  }
}
</code></pre>
<pre><code class="language-erlang">  { ok, Pid } = dotnet_shim:start_link(<span class="hljs-string">&quot;priv/acme.dll&quot;</span>, <span class="hljs-string">&quot;Acme.MyEnterpriseGradeApp&quot;</span> ),

  <span class="hljs-comment">%% Hello Robert</span>
  Pid ! <span class="hljs-string">&quot;Hello Robert&quot;</span>.
</code></pre>
<p>Yes, this just works - arbitrary messages sent from Erlang to a process started (and running!) in dotnet arrive and get translated accordingly. How about doing something with state then?</p>
<pre><code class="language-csharp"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">AdditionServer</span> : <span class="hljs-title">IHandleCall</span>&lt;<span class="hljs-title">int</span>&gt; {
  <span class="hljs-keyword">private</span> <span class="hljs-built_in">int</span> total = <span class="hljs-number">0</span>;

  <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">HandleCall</span>(<span class="hljs-params">HandleCallContext ctx, <span class="hljs-built_in">int</span> msg</span>)</span> {
    <span class="hljs-keyword">this</span>.total += msg;
    <span class="hljs-keyword">return</span> ctx.Reply(total);
  }
}

<span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">AdditionApp</span> : <span class="hljs-title">IApp</span> {
  <span class="hljs-function"><span class="hljs-keyword">public</span> Object <span class="hljs-title">Start</span>(<span class="hljs-params"></span>)</span> { 
    <span class="hljs-keyword">return</span> GenServer.StartLink(() =&gt; <span class="hljs-keyword">new</span> AdditionServer());
  }
}</code></pre>
<pre><code class="language-erlang">  { ok, Pid } = dotnet_shim:start_link(<span class="hljs-string">&quot;priv/acme.dll&quot;</span>, <span class="hljs-string">&quot;Acme.AdditionApp&quot;</span> ),

  <span class="hljs-comment">%% 1</span>
  ?LOG(gen_server:call(Pid, <span class="hljs-number">1</span>)),
  <span class="hljs-comment">%% 5</span>
  ?LOG(gen_server:call(Pid, <span class="hljs-number">4</span>)),
  <span class="hljs-comment">%% 11</span>
  ?LOG(gen_server:call(Pid, <span class="hljs-number">6</span>)),
</code></pre>
<p>In Erlang we&#39;d have a state record that needs returning as part of the handle_info callback, but that is because Erlang doesn&#39;t have mutation. Dotnet is somewhat fuller featured in this regard and we can just store our state on a member variable and forgo the extra steps required to dance around immutable structures.</p>
<p><em>Pattern Matching in Dotnet</em></p>
<p>Now you&#39;ll notice that our IHandleInfo/IHandleCall interfaces are generic and take the input shape expected, but it&#39;s really common in Erlang for a handle_info call to take a multitude of shapes and perform pattern matching based on those shapes to perform the correct block of logic.</p>
<p>Consider this code written in Erlang</p>
<pre><code class="language-erlang">
handle_info({tell_me, Pid}, State = #state { value = Value }) -&gt; 
  Pid ! Value,
  {noreply, State};
handle_info({op, {add, X}}), State = #state { value = Value }) -&gt; 
  {noreply, State#state { value = Value + X }};
handle_info({op, {mul, X}}), State = #state { value = Value }) -&gt; 
  {noreply, State#state { value = Value * X }}.
</code></pre>
<p>This code either receives a <em>{ atom(), pid() }</em>, or <em>{ atom(), { atom(), integer() }}</em>, we don&#39;t have union types in dotnet so can&#39;t map this across cleanly - or <em>can we</em>. C# has some semblance of pattern matching these days as any good scripting language should - what if we just request &#39;Object&#39; as our message type instead?</p>
<pre><code class="language-csharp"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">MyCoolGenServer</span> : <span class="hljs-title">IHandleInfo</span>&lt;<span class="hljs-title">Object</span>&gt; {
  <span class="hljs-keyword">private</span> <span class="hljs-built_in">int</span> <span class="hljs-keyword">value</span> = <span class="hljs-number">0</span>;

  <span class="hljs-function"><span class="hljs-keyword">public</span> HandleInfoResult <span class="hljs-title">HandleInfo</span>(<span class="hljs-params">HandleInfoContext ctx, Object msg</span>)</span> {
    <span class="hljs-keyword">switch</span>(msg) {
      <span class="hljs-keyword">case</span> Tuple&lt;Atom, Pid&gt; t <span class="hljs-keyword">when</span> t.Item1 == <span class="hljs-string">&quot;tell_me&quot;</span>:
        Erlang.Send(t.Item2, <span class="hljs-keyword">this</span>.<span class="hljs-keyword">value</span>);
        <span class="hljs-keyword">break</span>;
      <span class="hljs-keyword">case</span> Tuple&lt;Atom, Tuple&lt;Atom, Int&gt;&gt; <span class="hljs-keyword">when</span> t.Item1 == <span class="hljs-string">&quot;op&quot;</span> 
                                         &amp;&amp; t.Item2.Item1 == <span class="hljs-string">&quot;add&quot;</span>:
        <span class="hljs-keyword">this</span>.<span class="hljs-keyword">value</span> += t.Item2.Item2;
        <span class="hljs-keyword">break</span>;
      <span class="hljs-keyword">case</span> Tuple&lt;Atom, Tuple&lt;Atom, Int&gt;&gt; <span class="hljs-keyword">when</span> t.Item1 == <span class="hljs-string">&quot;op&quot;</span> 
                                         &amp;&amp; t.Item2.Item1 == <span class="hljs-string">&quot;mul&quot;</span>:
        <span class="hljs-keyword">this</span>.<span class="hljs-keyword">value</span> *= t.Item2.Item2;
        <span class="hljs-keyword">break</span>;
      <span class="hljs-literal">default</span>:
        <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> TermException(<span class="hljs-string">&quot;Unsupported message received&quot;</span>);
    }
    <span class="hljs-keyword">return</span> ctx.NoReply();
  }
}</code></pre>
<p>Okay it&#39;s not the nicest example in the world but it <em>works</em>. <em>Atom</em> and <em>Pid</em> by the way are C# types that wrap the <em>concept</em> of an Atom (just a string really) and an instance of a <em>Pid</em> respectively. An Erlang static class exists for doing things like sending data to an arbitrary pid and that&#39;s what is invoked in that above code. </p>
<p>Now that&#39;s interesting, <em>Erlang.Send</em>? That smells a lot like we&#39;re calling Erlang from dotnet and you know why? It&#39;s because we&#39;re calling Erlang from dotnet.</p>
<p><em>Using Dynamic to invoke arbitrary Erlang code from Dotnet</em></p>
<p>There is absolutely no point in writing gen servers in dotnet if we then go and use the dotnet File or Sockets API (or perform any other IO for that matter). One of the more glorious aspects of writing Erlang is that when you&#39;re opening handles to various IO, you&#39;re actually spinning up processes that are linked to an owner and a pile of excellent behaviour is there by default to ensure that if the host crashes that the supervision tree will handle that, restart appropriate children and those handles will get <em>closed cleanly</em>. This is <em>baked right into OTP</em> and is one of the reasons why implementions of actor models in platforms such as Java/Scala (Akka) are missing 100% of the shots they&#39;re taking. (This also goes double for implementing these patterns using <a href="http://codeofrob.com/entries/the-ashton-disinterest-curve---clojure.html">core.async in Clojure</a> but I digress)</p>
<p>It makes sense therefore to just allow the execution of arbitrary Erlang code from dotnet and therefore open access to these APIs.</p>
<p>Consider <em><a href="https://erlang.org/doc/man/file.html#write_file-2">file:write_file</a></em> for example</p>
<pre><code class="language-csharp">  result = Erlang.Modules.File.WriteFile(&quot;foo.txt&quot;, Encoding.ASCII.GetBytes(&quot;please write me to that file));
  switch(result) {
    case Atom a when a == &quot;ok&quot;: 
      return;
    default: 
      throw new TermException&quot;That didn&#x27;t work&quot;);
  }</code></pre>
<p>Works out of the box. How about <em><a href="https://erlang.org/doc/man/file.html#open-2">file:open</a></em>, <em><a href="https://erlang.org/doc/man/file.html#write-2">file:write</a></em> and <em><a href="https://erlang.org/doc/man/file.html#close-1">file:close</a></em>?</p>
<p>Like most of the Erlang APIs, file:open effectively returns a pid which is linked to the parent process. This also <em>just works</em> in Erlang.NET.</p>
<pre><code class="language-csharp">
  <span class="hljs-comment">// Open the file handle and stash the pid for future use</span>
  Tuple &lt;Atom, Pid&gt; success = (Tuple&lt;Atom,Pid&gt;)Erlang.Modules.File.Open(<span class="hljs-string">&quot;file.txt&quot;</span>, <span class="hljs-keyword">new</span> <span class="hljs-built_in">object</span>[] { <span class="hljs-keyword">new</span> Atom(<span class="hljs-string">&quot;write&quot;</span>) } );
  <span class="hljs-keyword">this</span>.pid = success.Item2;

  <span class="hljs-comment">// And then do some of this</span>
  Erlang.Modules.File.Write(<span class="hljs-keyword">this</span>.pid, data);
  Erlang.Modules.File.Write(<span class="hljs-keyword">this</span>.pid, data);
  Erlang.Modules.File.Write(<span class="hljs-keyword">this</span>.pid, data);

  <span class="hljs-comment">// And at some point</span>
  Erlang.Modules.File.Close(<span class="hljs-keyword">this</span>.pid);
  <span class="hljs-keyword">this</span>.pid = ErlNifPid.Zero;

</code></pre>
<p>In a similar vein, that also means that APIs that involve messages being sent back to the parent process work as well - this can either be implemented in the IHandleInfo as above, or we can spin up an arbitrary process in dotnet to handle those specific messages. Doing this and wrapping this functionality in a dotnet class is a far more pleasant way of hiding the low level dynamic call taking place and exporting a nicer API to the dotnet client.</p>
<pre><code class="language-csharp">  <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">class</span> <span class="hljs-title">GenUdp</span> {

  <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> Pid <span class="hljs-title">Open</span>(<span class="hljs-params">Tuple&lt;Int, Int, Int, Int&gt; ip, <span class="hljs-built_in">int</span> port</span>)</span> {
     Pid parent = Erlang.Self();
     <span class="hljs-keyword">return</span> Process.Spawn((Process ctx) =&gt; {
      Tuple&lt;Atom, Pid&gt; success = (Tuple&lt;Atom, Pid&gt;)Erlang.Modules.GenUdp.Open(port, 
      <span class="hljs-keyword">new</span> <span class="hljs-built_in">object</span>[] { Tuple.Create(<span class="hljs-keyword">new</span> Atom(<span class="hljs-string">&quot;ip&quot;</span>), ip)
                   , Tuple.Create(<span class="hljs-keyword">new</span> Atom(<span class="hljs-string">&quot;active&quot;</span>), <span class="hljs-literal">true</span>)
                   }
      });
      <span class="hljs-keyword">return</span> ReceiveLoop(parent, process);
    });
  }


  <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> ProcessResult <span class="hljs-title">ReceiveLoop</span>(<span class="hljs-params">Pid parent, Process process</span>)</span> {
    process.Receive((Process process, Object msg) =&gt; {
      <span class="hljs-keyword">switch</span>(msg) {
        <span class="hljs-keyword">case</span> Tuple&lt;Atom, Pid, Tuple&lt;Int,Int,Int,Int&gt;, Int, Byte[]&gt; data: 
          Erlang.send(parent, data.Item5);
          <span class="hljs-keyword">return</span> ReceiveLoop(parent, process);
        <span class="hljs-literal">default</span>:
          <span class="hljs-keyword">return</span> process.Finish(<span class="hljs-keyword">new</span> Atom(<span class="hljs-string">&quot;ok&quot;</span>));
      }
    })
  }

  <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">Stop</span>(<span class="hljs-params">Pid pid</span>)</span> {
    Erlang.Send(pid, <span class="hljs-keyword">new</span> Atom(<span class="hljs-string">&quot;stop&quot;</span>));
  }</code></pre>
<p>And this would allow us to write a gen server which connects to a udp socket and writes everything it receives to disk. (Assuming we&#39;ve wrapped file:open/etc the same way as we just did with UDP)</p>
<pre><code class="language-csharp">
  <span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">UdpToFileServer</span> : <span class="hljs-title">IHandleInfo</span>&lt;<span class="hljs-title">Byte</span>[]&gt;, <span class="hljs-title">IHandleTerminate</span> {
    <span class="hljs-keyword">private</span> Pid udp;
    <span class="hljs-keyword">private</span> Pid file;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">UdpToFileServer</span>(<span class="hljs-params">String filename, Tuple&lt;Int,Int,Int,Int&gt; ip, <span class="hljs-built_in">int</span> port</span>)</span> {
      <span class="hljs-keyword">this</span>.udp = GenUdp.Open(Tuple.Create(ip, port));
      <span class="hljs-keyword">this</span>.file = ErlangFile.Open(filename, <span class="hljs-keyword">new</span> <span class="hljs-built_in">object</span>[] { <span class="hljs-keyword">new</span> Atom(<span class="hljs-string">&quot;write&quot;</span>) } );
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> HandleInfoResult <span class="hljs-title">HandleInfo</span>(<span class="hljs-params">HandleInfoContext ctx, Byte[] bin</span>)</span> {
      ErlangFile.Write(<span class="hljs-keyword">this</span>.file, bin);
    }

    <span class="hljs-comment">// Not necessary, but be kind</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">Terminate</span>(<span class="hljs-params"></span>)</span> {
      GenUdp.Stop(udp);
      ErlangFile.Close(file);
    }
  }
</code></pre>
<p><em>Building more of the application in dotnet itself</em></p>
<p>So far we&#39;ve demonstrated how you can invoke arbitary code written in dotnet from Erlang, spin up processes written in dotnet (either as standalone processes or as gen servers), and invoke arbitrary Erlang code from dotnet as well as all the magic type back and forth nonsense we&#39;ve managed to pack into this library.</p>
<p>What if we want to build more complex functionality in dotnet? It&#39;s one thing spinning up a single process which then spins up ad-hoc processes itself, but to build a proper reliable application in dotnet what we need is the ability to define supervision trees!</p>
<p>In Erlang, typically the application will spin up a top level supervision tree - which is effectively a list of ids, and then modules/args to invoke for those ids in order to get a process. If one of these processes crash then depending on how that supervision tree is configured, either the whole tree will be restarted, or just the child that crashed (and then repeated crashes might then cause the supervisor itself to restart). Some of these children can themselves be supervisors and thus with a little careful reasoning about how your application needs to interact, a tree can be built that maximises robustness whilst minimising any potential downtime.</p>
<p>In dotnet... Well we can just do all of this in a single file - here is a supervision tree from one of the tests written in the Erlang.NET project itself.</p>
<pre><code class="language-csharp">    <span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">SimpleSupApp</span> : <span class="hljs-title">IApp</span>
    {
      <span class="hljs-function"><span class="hljs-keyword">public</span> Object <span class="hljs-title">Start</span>(<span class="hljs-params"></span>)</span> {
        <span class="hljs-keyword">return</span> Supervisor.StartLink(<span class="hljs-string">&quot;primary-sup&quot;</span>, 
                  () =&gt; <span class="hljs-keyword">new</span> SupervisorConfig(
                    SupervisionStrategy.OneForAll,
                    <span class="hljs-keyword">new</span> SupervisorChild [] { 
                       <span class="hljs-keyword">new</span> SupervisorWorker(<span class="hljs-string">&quot;c1&quot;</span>, () =&gt; GenServer.StartLink(<span class="hljs-string">&quot;genserver-one&quot;</span>, () =&gt; <span class="hljs-keyword">new</span> WorkerGenServer1()))
                     , <span class="hljs-keyword">new</span> SupervisorWorker(<span class="hljs-string">&quot;c2&quot;</span>, () =&gt; GenServer.StartLink(<span class="hljs-string">&quot;genserver-two&quot;</span>, () =&gt; <span class="hljs-keyword">new</span> WorkerGenServer1()))
                     , <span class="hljs-keyword">new</span> SupervisorWorker(<span class="hljs-string">&quot;c3&quot;</span>, () =&gt; GenServer.StartLink(<span class="hljs-string">&quot;genserver-three&quot;</span>, () =&gt; <span class="hljs-keyword">new</span> WorkerGenServer1()))
                     , <span class="hljs-keyword">new</span> Supervisor(<span class="hljs-string">&quot;s1&quot;</span>, () =&gt; 
                         Supervisor.StartLink(<span class="hljs-string">&quot;secondary-sup&quot;</span>, 
                         () =&gt; <span class="hljs-keyword">new</span> SupervisorConfig(SupervisionStrategy.OneForOne, 
                           <span class="hljs-keyword">new</span> [] { <span class="hljs-keyword">new</span> SupervisorWorker(<span class="hljs-string">&quot;sc1&quot;</span>, () =&gt; GenServer.StartLink(<span class="hljs-string">&quot;nested-one&quot;</span>, () =&gt; <span class="hljs-keyword">new</span> WorkerGenServer1()))
                                 ,  <span class="hljs-keyword">new</span> SupervisorWorker(<span class="hljs-string">&quot;sc2&quot;</span>, () =&gt; GenServer.StartLink(<span class="hljs-string">&quot;nested-two&quot;</span>, () =&gt; <span class="hljs-keyword">new</span> WorkerGenServer1()))
                                 ,  <span class="hljs-keyword">new</span> SupervisorWorker(<span class="hljs-string">&quot;sc3&quot;</span>, () =&gt; GenServer.StartLink(<span class="hljs-string">&quot;nested-three&quot;</span>, () =&gt; <span class="hljs-keyword">new</span> WorkerGenServer1()))
                                 })))
                     }));
      }
    }</code></pre>
<p>The resultant tree is along the lines of:</p>
<ul>
<li>PrimarySup<ul>
<li>c1 : WorkerGenServer1 (called genserver-one)</li>
<li>c2 : WorkerGenServer1 (called genserver-two)</li>
<li>c3 : WorkerGenServer1 (called genserver-three)</li>
<li>s1 : Supervisor (called secondary-sup)<ul>
<li>sc1 : WorkerGenServer1 (called nested-one)</li>
<li>sc2 : WorkerGenServer1 (called nested-two)</li>
<li>sc3 : WorkerGenServer1 (called nested-three)</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>And then we have the following behaviours</p>
<ul>
<li>Invoking <em>sys:terminate(Pid, &#39;arse&#39;)</em> on c1,c2,c3 or even s1 will result in every single process in the tree being restarted</li>
<li>Invoking <em>sys:terminate(Pid, &#39;arse&#39;)</em> on sc1, sc2, sc3 will only result in that single process being restarted</li>
</ul>
<p>By restarted, we mean that callback above (the stubby lambda ()=&gt;) being invoked once again. Args can be captured and passed in here if required, it&#39;s just closures all the way down.</p>
<p><em>Conclusion</em> </p>
<p>Now while all the examples in this blog entry are written in C# (as that appears to be the prevailing language in that ecosystem for the moment, yes I know there are F# developers too <em>waves at all five of them</em>), all of this results in our original aim which was to write our gen servers in Visual Basic .NET.</p>
<pre><code class="language-vb">    <span class="hljs-keyword">Public</span> <span class="hljs-keyword">Class</span> MyGenServerVB
        <span class="hljs-keyword">Inherits</span> IHandleInfo(<span class="hljs-keyword">Of</span> Msg)
        <span class="hljs-keyword">Public</span> <span class="hljs-keyword">Sub</span> <span class="hljs-built_in">New</span>()
        <span class="hljs-keyword">End</span> <span class="hljs-keyword">Sub</span>
        <span class="hljs-keyword">Public</span> <span class="hljs-keyword">Function</span> HandleInfo(<span class="hljs-keyword">ByVal</span> ctx <span class="hljs-keyword">As</span> HandleInfoContext, <span class="hljs-keyword">ByVal</span> msg <span class="hljs-keyword">As</span> Msg) <span class="hljs-keyword">As</span> HandleInfoResult
          <span class="hljs-keyword">If</span> msg.Item1 = <span class="hljs-string">&quot;hello bob&quot;</span> <span class="hljs-keyword">Then</span>
            Erlang.Send(msg.Item2, <span class="hljs-string">&quot;hello joe&quot;</span>)
          <span class="hljs-keyword">Else</span>
            Erlang.Send(msg.Item2, <span class="hljs-string">&quot;weeee&quot;</span>)
          <span class="hljs-keyword">End</span> <span class="hljs-keyword">If</span>
          <span class="hljs-keyword">Return</span> ctx.NoReply()
        <span class="hljs-keyword">End</span> <span class="hljs-keyword">Function</span>
    <span class="hljs-keyword">End</span> <span class="hljs-keyword">Class</span></code></pre>
<p>That&#39;s all it took, I&#39;ll be following this blog entry up with how any of this works at all - so subscribe to the RSS (lol) if you want to read that, that&#39;ll be all the technical stuff that you don&#39;t know you needed to know in order to appreciate the &#39;it just works&#39; nature of this integration if that&#39;s all you wanted.</p>
<p>Take a look over at the Github for the actual <a href="https://github.com/robashton/erlang.net/wiki/Getting-Started">Getting Started</a> notes, there will no doubt be tweaks required but it should be enough for us to make some progress at least.</p>
<p>Also no guarantees it works on Windows, pull requests are open.</p>
]]></description><link>http://codeofrob.com/entries/write-your-erlang-gen-servers-in-visual-basic.html</link><guid isPermaLink="true">http://codeofrob.com/entries/write-your-erlang-gen-servers-in-visual-basic.html</guid><dc:creator><![CDATA[Rob Ashton]]></dc:creator><pubDate>Thu, 01 Apr 2021 09:30:00 GMT</pubDate></item><item><title><![CDATA[Integrating C# with Legacy Elixir Projects]]></title><description><![CDATA[<p>Hot on the heels of my last post about <a href="/entries/write-your-erlang-gen-servers-in-visual-basic.html">integrating Dotnet with Erlang</a>, I was asked by a friend &quot;Hey that looks really cool, we&#39;re stuck with Elixir at work currently - is there a migration path for us?</p>
<p>Well I&#39;m glad you asked, <a href="https://github.com/robashton/erlang.net">Erlang.NET</a> does indeed work with Elixir and to prove it, I&#39;ve <a href="https://github.com/robashton/elixir.net">built a skeleton application</a> over on Github.</p>
<h1 id="what-does-it-look-like">What does it look like?</h1>
<p>Well, first of all let me say that I&#39;ve never worked with Elixir before, I don&#39;t generally like to get my hands dirty with legacy techologies, and I was never a huge fan of Ruby, so the idea of writing my Erlang with Ruby syntax never appealed either, but for science...</p>
<p>Let&#39;s say I&#39;ve got an application in Elixir</p>
<pre><code class="language-elixir">    { ok, result } = add_these_numbers(<span class="hljs-number">5</span>,<span class="hljs-number">3</span>)
    IO.puts <span class="hljs-string">&quot;What a result: <span class="hljs-subst">#{result}</span>&quot;</span></code></pre>
<p>And I&#39;m not satisfied with the way in which Elixirs adds these numbers together, but I do have some C# that does this much better?</p>
<p>Well, first off we add the Erlang.NET dependency to our mix.exs</p>
<pre><code class="language-elixir">  <span class="hljs-function"><span class="hljs-keyword">defp</span> <span class="hljs-title">deps</span></span> <span class="hljs-keyword">do</span>
    [
      {<span class="hljs-symbol">:dotnet</span>, <span class="hljs-symbol">git:</span> <span class="hljs-string">&quot;https://github.com/robashton/erlang.net.git&quot;</span>, <span class="hljs-symbol">branch:</span> <span class="hljs-string">&quot;master&quot;</span>}
    ]</code></pre>
<p>And make sure that the dotnet application is going to start along with our own</p>
<pre><code class="language-elixir">  <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">application</span></span> <span class="hljs-keyword">do</span>
      [
        <span class="hljs-symbol">extra_applications:</span> [<span class="hljs-symbol">:logger</span>, <span class="hljs-symbol">:dotnet</span>],
        <span class="hljs-symbol">mod:</span> {Eg, []},
      ]
  <span class="hljs-keyword">end</span></code></pre>
<p>Rather than use Nuget and get Yet Another Package Manager on my machine, I chose to use Mix for this project to get my dependencies and just write some MSBuild because it&#39;s a really powerful way of defining builds in Dotnet and can do pretty much anything we ask of it. I created a dotnet project in the &#39;cs&#39; directory of my Alixer project that looks like this.</p>
<pre><code class="language-xml"><span class="hljs-tag">&lt;<span class="hljs-name">Project</span> <span class="hljs-attr">Sdk</span>=<span class="hljs-string">&quot;Microsoft.NET.Sdk&quot;</span>&gt;</span>

  <span class="hljs-tag">&lt;<span class="hljs-name">PropertyGroup</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">TargetFramework</span>&gt;</span>net5.0<span class="hljs-tag">&lt;/<span class="hljs-name">TargetFramework</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">EnableDynamicLoading</span>&gt;</span>true<span class="hljs-tag">&lt;/<span class="hljs-name">EnableDynamicLoading</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">CopyLocalLockFileAssemblies</span>&gt;</span>true<span class="hljs-tag">&lt;/<span class="hljs-name">CopyLocalLockFileAssemblies</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">PropertyGroup</span>&gt;</span>

  <span class="hljs-tag">&lt;<span class="hljs-name">ItemGroup</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">ProjectReference</span> <span class="hljs-attr">Include</span>=<span class="hljs-string">&quot;../deps/dotnet/cslib/Erlang.csproj&quot;</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">Content</span> <span class="hljs-attr">Include</span>=<span class="hljs-string">&quot;../deps/dotnet/priv/liberldotnet.so&quot;</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">CopyToOutputDirectory</span>&gt;</span>PreserveNewest<span class="hljs-tag">&lt;/<span class="hljs-name">CopyToOutputDirectory</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">Content</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">ItemGroup</span>&gt;</span>

<span class="hljs-tag">&lt;/<span class="hljs-name">Project</span>&gt;</span></code></pre>
<p>This means I need to configure the Erlang dotnet application to use the assemblies from the built location, no worries</p>
<pre><code class="language-elixir"><span class="hljs-keyword">import</span> Config

config <span class="hljs-symbol">:dotnet</span>,
  <span class="hljs-symbol">runtime_config:</span> to_charlist(<span class="hljs-string">&quot;cs/bin/Debug/net5.0/Eg.runtimeconfig.json&quot;</span>),
  <span class="hljs-symbol">runtime_dll:</span> to_charlist(<span class="hljs-string">&quot;cs/bin/Debug/net5.0/Erlang.dll&quot;</span>)</code></pre>
<p>Whew, Elixering sure is <em>hard work</em> I can see why you&#39;d want to move away from it! Almost there though.</p>
<p>Anyway, this means I can use my far better function in dotnet by writing a class</p>
<pre><code class="language-csharp">    public class App : IApp&lt;Tuple&lt;int, int&gt;&gt;
    {
      public Object Start(Tuple&lt;int, int&gt; t) {
        return t.Item1 + t.Item2;
      }
    }</code></pre>
<p>And call this from Elixir like so</p>
<pre><code class="language-elixir">    { <span class="hljs-symbol">:ok</span>, result } = <span class="hljs-symbol">:dotnet</span>.run_app_from_assembly(to_charlist(<span class="hljs-string">&quot;cs/bin/Debug/net5.0/Eg.dll&quot;</span>), to_charlist(<span class="hljs-string">&quot;Eg.App&quot;</span>), { <span class="hljs-number">5</span>, <span class="hljs-number">3</span> })
    IO.puts <span class="hljs-string">&quot;What a result: <span class="hljs-subst">#{result}</span>&quot;</span></code></pre>
<p>Far better than the original, although for some reason Elixir likes to use byte arrays for its strings when dotnet wants char lists so we have to do some conversion to get from the legacy elixir.</p>
<p>This of course allows us to then use gen servers written in dotnet, and over time we can move away from alikser altogether.</p>
<pre><code class="language-elixir"> <span class="hljs-symbol">:dotnet</span>.run_app_from_assembly(to_charlist(<span class="hljs-string">&quot;cs/bin/Debug/net5.0/Eg.dll&quot;</span>), to_charlist(<span class="hljs-string">&quot;Eg.Gen&quot;</span>), %{ <span class="hljs-symbol">:foo</span> =&gt; <span class="hljs-number">1</span>, <span class="hljs-symbol">:bar</span> =&gt; <span class="hljs-number">2</span> })</code></pre>
<pre><code class="language-csharp">    <span class="hljs-keyword">public</span> <span class="hljs-keyword">record</span> <span class="hljs-title">GenArgs</span> {
        <span class="hljs-keyword">public</span> <span class="hljs-built_in">int</span> Foo { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">init</span>; }
        <span class="hljs-keyword">public</span> <span class="hljs-built_in">int</span> Bar { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">init</span>; }
    }

    <span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">MyGen</span> : <span class="hljs-title">IHandleCall</span>&lt;<span class="hljs-title">Atom</span>&gt; { 
      GenArgs args;

      <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">MyGen</span>(<span class="hljs-params">GenArgs args</span>)</span> {
        <span class="hljs-keyword">this</span>.args = args;
      }

      <span class="hljs-function"><span class="hljs-keyword">public</span> HandleCallResult <span class="hljs-title">HandleCall</span>(<span class="hljs-params">HandleCallContext ctx, Atom picker</span>)</span> {
        <span class="hljs-keyword">switch</span>(picker) {
          <span class="hljs-keyword">case</span> <span class="hljs-string">&quot;foo&quot;</span>: 
            <span class="hljs-keyword">return</span> ctx.Reply(<span class="hljs-keyword">this</span>.args.Foo);
          <span class="hljs-keyword">case</span> <span class="hljs-string">&quot;bar&quot;</span>: 
            <span class="hljs-keyword">return</span> ctx.Reply(<span class="hljs-keyword">this</span>.args.Bar);
          <span class="hljs-literal">default</span>:
            <span class="hljs-keyword">return</span> ctx.Reply(<span class="hljs-keyword">new</span> Atom(<span class="hljs-string">&quot;nope&quot;</span>));
        }
      }
    }


    <span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">Gen</span> : <span class="hljs-title">IApp</span>&lt;<span class="hljs-title">GenArgs</span>&gt;
    {
      <span class="hljs-function"><span class="hljs-keyword">public</span> Object <span class="hljs-title">Start</span>(<span class="hljs-params">GenArgs args</span>)</span> {
        <span class="hljs-keyword">return</span> GenServer.StartLink(() =&gt; <span class="hljs-keyword">new</span> MyGen(args));
      }
    }</code></pre>
<p>I hope this answers the question and helps with people struggling to move away from their legacy elixir projects, always happy to help.</p>
]]></description><link>http://codeofrob.com/entries/integrating-c-with-legacy-elixir-projects.html</link><guid isPermaLink="true">http://codeofrob.com/entries/integrating-c-with-legacy-elixir-projects.html</guid><dc:creator><![CDATA[Rob Ashton]]></dc:creator><pubDate>Thu, 01 Apr 2021 09:30:00 GMT</pubDate></item><item><title><![CDATA[Encoding h264 with Nvidia]]></title><description><![CDATA[<p>This blog entry is part of my &quot;<a href="/entries/blogging-the-mundane.html">blog about mundane stuff</a>&quot; series.</p>
<p>I covered my <a href="/entries/decoding-h264-with-nvidia.html">decoding</a> test before having a look at <a href="/entries/cuda-context-management-with-nvenc.html">context management</a>, so now it&#39;s time to look at re-encoding the h264 and demonstrating a round trip through the nvidia hardware.</p>
<h1 id="what-we-have-already">What we have already</h1>
<p>We had this workflow for testing</p>
<pre><code>
  #workflow {
    generator = #read_from_ts { name = source, filename  = &lt;&lt;<span class="hljs-string">&quot;foo.ts&quot;</span>&gt;&gt; },
    processors = [
      #nvidia_decoder { name = decode, <span class="hljs-keyword">from</span> = { source, ?video_frames_with_stream_id(<span class="hljs-number">256</span>) } },
      #x264_encoder { name = encode, <span class="hljs-keyword">from</span> = decode },
      #ts_writer { name = write, <span class="hljs-keyword">from</span> = encode, filename  = &lt;&lt;<span class="hljs-string">&quot;out.ts&quot;</span>&gt;&gt; }
    ]
  }

</code></pre><p>and what I want is</p>
<pre><code>  #workflow {
    generator = #read_from_ts { name = source, filename  = &lt;&lt;<span class="hljs-string">&quot;foo.ts&quot;</span>&gt;&gt; },
    processors = [
      #nvidia_decoder { name = decode, <span class="hljs-keyword">from</span> = { source, ?video_frames_with_stream_id(<span class="hljs-number">256</span>) } },
      #nvidia_encoder { name = encode, <span class="hljs-keyword">from</span> = decode },
      #ts_writer { name = write, <span class="hljs-keyword">from</span> = encode, filename  = &lt;&lt;<span class="hljs-string">&quot;out.ts&quot;</span>&gt;&gt; }
    ]
  }
</code></pre><p>In the decode entry we had a series of pointers to surfaces that we&#39;d pulled out of the decoder along with the corresponding timestamps, these are in NV12 planar format and byte-aligned (and I&#39;m storing all that information alongside the pointer to that surface in a struct so now we just need to see what the API looks like to turn this surface into h264 once again...)</p>
<p>This looks something like this (It actually looks nothing like this as most of this info is stored in a linked list tied to a central pool which contains the shared information), but this is at least representative of what we have.</p>
<pre><code>
  <span class="hljs-keyword">typedef</span> <span class="hljs-class"><span class="hljs-keyword">struct</span> _<span class="hljs-title">nvidia_allocated_surface</span>  {</span>
    <span class="hljs-keyword">uint8_t</span>* data;
    <span class="hljs-keyword">int</span> bpp;
    <span class="hljs-keyword">int</span> byte_width;
    <span class="hljs-keyword">int</span> byte_height;
    <span class="hljs-keyword">size_t</span> pitch;
  } nvidia_allocated_surface;
</code></pre><p>This surface is allocated <em>on the GPU</em> via CUDA, and the GPU is where we want to do our encode so hopefully we can pretty much use this data directly.</p>
<h1 id="the-api">The API</h1>
<p>The encode API looks nothing like the decode API in that it&#39;s sat in its own header file (which is again expected to be included as part of the repo, but the library we&#39;re going to be loading is <em>definitely</em>  expected to exist on the runtime as part of the driver install.</p>
<ul>
<li><em>Include/nvEncodeAPI.h</em> contains all definitions/enums/functions/etc</li>
</ul>
<p>and somewhere on the host OS installed as part of the driver package (for me, /run/opengl-driver/lib/)</p>
<ul>
<li><em>libnvidia-encode.so</em></li>
</ul>
<h1 id="creating-the-api">Creating the API</h1>
<p>The functions that we end up using are loaded as a struct of function pointers and we actually only link a single function directly from that library to get hold of that struct. As a consequence of this, every struct being passed into a function in this API tends to be versioned indepedendently, such is life.</p>
<pre><code class="language-c">
  <span class="hljs-keyword">uint32_t</span> version = <span class="hljs-number">0</span>;
  <span class="hljs-keyword">uint32_t</span> currentVersion = (NVENCAPI_MAJOR_VERSION &lt;&lt; <span class="hljs-number">4</span>) | NVENCAPI_MINOR_VERSION;
  NV_ENCODE_API_FUNCTION_LIST nvenc = {NV_ENCODE_API_FUNCTION_LIST_VER};

  NvEncodeAPIGetMaxSupportedVersion(&amp;version);
  <span class="hljs-keyword">if</span> (currentVersion &gt; version)
  {
    <span class="hljs-keyword">return</span> <span class="hljs-number">-1</span>; <span class="hljs-comment">// or whatever</span>
  }

  NvEncodeAPICreateInstance(&amp;nvenc);

  <span class="hljs-comment">// use the functions on nvenc</span>
</code></pre>
<p>This doesn&#39;t do anything other than a <em>dlopen</em> of the library exporting the functions and copy the pointers to those functions onto the nvenc struct so they can be called. Invoke it once, cache the results somewhere and then we can get to the business of talking to the GPU.</p>
<h1 id="creating-an-encoder">Creating an encoder</h1>
<p>Unlike the decode stack, the encoder doesn&#39;t seem to be built <em>directly</em> on top of CUDA, it having the capability of instantiating on top of OpenGL/DirectX/Cuda as options (and then utilise surfaces from those systems). Because we&#39;re using the decoder (and planning on using CUDA to run upscaling algorithms and such), it makes sense to use CUDA for the encoder too.</p>
<p>Because of this, we&#39;ll want to use our already-created CUDA context and pass this into the open session call.</p>
<pre><code>
  NV_ENC_OPEN_ENCODE_SESSION_EX_PARAMS <span class="hljs-attr">encodeSessionExParams</span> = { NV_ENC_OPEN_ENCODE_SESSION_EX_PARAMS_VER };
  encodeSessionExParams.<span class="hljs-attr">device</span> = ctx;
  encodeSessionExParams.<span class="hljs-attr">deviceType</span> = NV_ENC_DEVICE_TYPE_CUDA;
  encodeSessionExParams.<span class="hljs-attr">apiVersion</span> = NVENCAPI_VERSION;
  void* <span class="hljs-attr">encoder</span> = NULL;

  nvenc.nvEncOpenEncodeSessionEx(&amp;encodeSessionExParams, &amp;encoder);
</code></pre><p>Now, this doesn&#39;t do very much other than give us an encode session that isn&#39;t initialise - and to initialise it we need to tell it what form our desired output needs to take. It is entirely possible to spend a day or two wondering why this call gives you back &#39;NV_ENC_ERR_INVALID_PARAM&#39; if it&#39;s not set up correctly (and reading the sample code doesn&#39;t help because the configuration of the encoder happens across multiple files because of the way that the samples are written), the below seems to be the the minimum required..</p>
<p>In the Real World (tm) we have an input surface with a known width/height from the decoder, here we&#39;ll hard code it along with the frame rate (I know my source is 25fps). In the Real World a load of these args will be passed in from Erlang, not C.</p>
<pre><code class="language-c">
  NV_ENC_INITIALIZE_PARAMS initializeParams = { NV_ENC_INITIALIZE_PARAMS_VER };
  NV_ENC_CONFIG encodeConfig = { NV_ENC_CONFIG_VER };
  NV_ENC_PRESET_CONFIG presetConfig = { NV_ENC_PRESET_CONFIG_VER, { NV_ENC_CONFIG_VER } };

  initializeParams.encodeConfig = &amp;encodeConfig;

  <span class="hljs-comment">// The essentials</span>
  initializeParams-&gt;encodeGUID = NV_ENC_CODEC_H264_GUID;
  initializeParams-&gt;presetGUID = NV_ENC_PRESET_P4_GUID;

  <span class="hljs-comment">// These need to line up with the input surface dimensions</span>
  initializeParams-&gt;encodeWidth = <span class="hljs-number">576</span>;
  initializeParams-&gt;encodeHeight = <span class="hljs-number">720</span>;

  <span class="hljs-comment">// Ditto these</span>
  initializeParams-&gt;frameRateNum = <span class="hljs-number">25</span>;
  initializeParams-&gt;frameRateDen = <span class="hljs-number">1</span>;

  <span class="hljs-comment">// I seemed to need these as well</span>
  initializeParams.enablePTD = <span class="hljs-number">1</span>;
  initializeParams.encodeConfig-&gt;frameIntervalP = <span class="hljs-number">3</span>;
  initializeParams.encodeConfig-&gt;gopLength = <span class="hljs-number">50</span>;
  initializeParams.tuningInfo = NV_ENC_TUNING_INFO_HIGH_QUALITY;

</code></pre>
<p>Once this initialize params basics is set up, we can ask the encoder to populate the actual details for us based on the preset and codec specified in the &#39;essentials&#39;</p>
<pre><code class="language-c">
  nvenc.nvEncGetEncodePresetConfigEx(encode_session-&gt;encoder, initializeParams.encodeGUID, initializeParams.presetGUID, tuningInfo, &amp;presetConfig);
  <span class="hljs-built_in">memcpy</span>(initializeParams.encodeConfig, &amp;presetConfig.presetCfg, <span class="hljs-keyword">sizeof</span>(NV_ENC_CONFIG));
</code></pre>
<p>I&#39;m not entirely sure why we don&#39;t just invoke nvEncGetEncoderPresetConfigEx on the struct already contained on the initializeParams, but the samples all end up doing this and the above code is precarious enough already (honestly, the number of ways this can go wrong with a single error is infuriating!). So we stick with the samples way of doing stuff!</p>
<p>I also needed to then go and set up the IDR frequency to match our requested gop length (the samples do this too) and not doing this resulted in NV_ENC_ERR_INVALID_PARAM so..</p>
<pre><code class="language-c">
    initializeParams.encodeConfig-&gt;encodeCodecConfig.h264Config.idrPeriod = initializeParams.encodeConfig-&gt;gopLength;
</code></pre>
<p>With all of the above done correctly, a call to the init fn will return a success and if not I&#39;m really sorry you&#39;re on your own because I&#39;ve served my time already.</p>
]]></description><link>http://codeofrob.com/entries/encoding-h264-with-nvidia.html</link><guid isPermaLink="true">http://codeofrob.com/entries/encoding-h264-with-nvidia.html</guid><dc:creator><![CDATA[Rob Ashton]]></dc:creator><pubDate>Thu, 19 Nov 2020 09:30:00 GMT</pubDate></item></channel></rss>