<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Tutorial: Dapr.Actors.Next by example on Dapr Docs</title><link>https://dapr.website.cncfstack.com/developing-applications/sdks/dotnet/dotnet-actors-next/tutorial/</link><description>Recent content in Tutorial: Dapr.Actors.Next by example on Dapr Docs</description><generator>Hugo</generator><language>en</language><atom:link href="https://dapr.website.cncfstack.com/developing-applications/sdks/dotnet/dotnet-actors-next/tutorial/index.xml" rel="self" type="application/rss+xml"/><item><title>Part 1: The cart, the modern baseline</title><link>https://dapr.website.cncfstack.com/developing-applications/sdks/dotnet/dotnet-actors-next/tutorial/dotnet-actorsnext-tutorial-cart/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dapr.website.cncfstack.com/developing-applications/sdks/dotnet/dotnet-actors-next/tutorial/dotnet-actorsnext-tutorial-cart/</guid><description>&lt;p>The first example is the smallest real actor: a cart that adds items, returns a summary, and abandons itself after twenty minutes idle via a timer. It does nothing exotic, and that is the point. It is the side-by-side against &lt;code>Dapr.Actors&lt;/code> that makes the modernization legible.&lt;/p>
&lt;p>Code for this part: &lt;code>/examples/Actor.Next/01-Cart/&lt;/code>.&lt;/p>
&lt;h2 id="what-you-build">What you build&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-csharp" data-lang="csharp">&lt;span class="line">&lt;span class="cl">&lt;span class="na">[GenerateActorClient]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kd">public&lt;/span> &lt;span class="k">interface&lt;/span> &lt;span class="nc">ICartActor&lt;/span> &lt;span class="p">:&lt;/span> &lt;span class="n">IActor&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Task&lt;/span> &lt;span class="n">AddItem&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">CartItem&lt;/span> &lt;span class="n">item&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">CancellationToken&lt;/span> &lt;span class="n">ct&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="k">default&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Task&lt;/span>&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="n">CartSummary&lt;/span>&lt;span class="p">&amp;gt;&lt;/span> &lt;span class="n">GetSummary&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">CancellationToken&lt;/span> &lt;span class="n">ct&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="k">default&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Task&lt;/span> &lt;span class="n">AbandonCart&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">CancellationToken&lt;/span> &lt;span class="n">ct&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="k">default&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kd">public&lt;/span> &lt;span class="kd">sealed&lt;/span> &lt;span class="k">record&lt;/span> &lt;span class="nc">CartItem&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="kt">string&lt;/span> &lt;span class="n">Sku&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kt">int&lt;/span> &lt;span class="n">Quantity&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kd">public&lt;/span> &lt;span class="kd">sealed&lt;/span> &lt;span class="k">record&lt;/span> &lt;span class="nc">CartSummary&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="kt">int&lt;/span> &lt;span class="n">ItemCount&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kt">decimal&lt;/span> &lt;span class="n">Total&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kt">bool&lt;/span> &lt;span class="n">Abandoned&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kd">public&lt;/span> &lt;span class="k">interface&lt;/span> &lt;span class="nc">IPricingClient&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">ValueTask&lt;/span>&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="kt">decimal&lt;/span>&lt;span class="p">&amp;gt;&lt;/span> &lt;span class="n">GetPriceAsync&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="kt">string&lt;/span> &lt;span class="n">sku&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">CancellationToken&lt;/span> &lt;span class="n">cancellationToken&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="k">default&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kd">public&lt;/span> &lt;span class="kd">sealed&lt;/span> &lt;span class="k">class&lt;/span> &lt;span class="nc">CartState&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">public&lt;/span> &lt;span class="n">Dictionary&lt;/span>&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="kt">string&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kt">int&lt;/span>&lt;span class="p">&amp;gt;&lt;/span> &lt;span class="n">Items&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="k">get&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="k">set&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="p">}&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="p">[];&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">public&lt;/span> &lt;span class="n">Dictionary&lt;/span>&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="kt">string&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kt">decimal&lt;/span>&lt;span class="p">&amp;gt;&lt;/span> &lt;span class="n">Prices&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="k">get&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="k">set&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="p">}&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="p">[];&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">public&lt;/span> &lt;span class="kt">bool&lt;/span> &lt;span class="n">Abandoned&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="k">get&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="k">set&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="na">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="na">[DaprActor(&amp;#34;Cart&amp;#34;)]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kd">public&lt;/span> &lt;span class="kd">sealed&lt;/span> &lt;span class="k">class&lt;/span> &lt;span class="nc">CartActor&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">ActorActivationContext&lt;/span> &lt;span class="n">context&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">IPricingClient&lt;/span> &lt;span class="n">pricing&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">IActorTimerScheduler&lt;/span> &lt;span class="n">timers&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">:&lt;/span> &lt;span class="n">Actor&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">ICartActor&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">private&lt;/span> &lt;span class="kd">static&lt;/span> &lt;span class="k">readonly&lt;/span> &lt;span class="n">TimeSpan&lt;/span> &lt;span class="n">AbandonAfter&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="n">TimeSpan&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">FromMinutes&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="m">20&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">protected&lt;/span> &lt;span class="kd">override&lt;/span> &lt;span class="n">ActorId&lt;/span> &lt;span class="n">Id&lt;/span> &lt;span class="p">=&amp;gt;&lt;/span> &lt;span class="n">context&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">ActorId&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">protected&lt;/span> &lt;span class="kd">override&lt;/span> &lt;span class="n">IActorStateAccessor&lt;/span> &lt;span class="n">State&lt;/span> &lt;span class="p">=&amp;gt;&lt;/span> &lt;span class="n">context&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">State&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">public&lt;/span> &lt;span class="kd">async&lt;/span> &lt;span class="n">Task&lt;/span> &lt;span class="n">AddItem&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">CartItem&lt;/span> &lt;span class="n">item&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">CancellationToken&lt;/span> &lt;span class="n">ct&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="k">default&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">var&lt;/span> &lt;span class="n">cart&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="k">await&lt;/span> &lt;span class="n">State&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">GetOrCreateAsync&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;cart&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">()&lt;/span> &lt;span class="p">=&amp;gt;&lt;/span> &lt;span class="k">new&lt;/span> &lt;span class="n">CartState&lt;/span>&lt;span class="p">(),&lt;/span> &lt;span class="n">ct&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">cart&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Value&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Items&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">item&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Sku&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="n">cart&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Value&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Items&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">GetValueOrDefault&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">item&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Sku&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">+&lt;/span> &lt;span class="n">item&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Quantity&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="c1">// mutate through .Value&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">cart&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Value&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Prices&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">item&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Sku&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="k">await&lt;/span> &lt;span class="n">pricing&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">GetPriceAsync&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">item&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Sku&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">ct&lt;/span>&lt;span class="p">);&lt;/span> &lt;span class="c1">// injected per activation&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">cart&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Value&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Abandoned&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="kc">false&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Re-arm the idle timer on every add; its callback is the AbandonCart method.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">await&lt;/span> &lt;span class="n">timers&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">RescheduleAsync&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;Cart&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">Id&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s">&amp;#34;abandon-cart&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">AbandonAfter&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">nameof&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">AbandonCart&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="kt">string&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Empty&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">cancellationToken&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">ct&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">public&lt;/span> &lt;span class="kd">async&lt;/span> &lt;span class="n">Task&lt;/span>&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="n">CartSummary&lt;/span>&lt;span class="p">&amp;gt;&lt;/span> &lt;span class="n">GetSummary&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">CancellationToken&lt;/span> &lt;span class="n">ct&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="k">default&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">var&lt;/span> &lt;span class="n">cart&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="k">await&lt;/span> &lt;span class="n">State&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">GetOrCreateAsync&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;cart&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">()&lt;/span> &lt;span class="p">=&amp;gt;&lt;/span> &lt;span class="k">new&lt;/span> &lt;span class="n">CartState&lt;/span>&lt;span class="p">(),&lt;/span> &lt;span class="n">ct&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">var&lt;/span> &lt;span class="n">itemCount&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="n">cart&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Value&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Items&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Values&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Sum&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">var&lt;/span> &lt;span class="n">total&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="n">cart&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Value&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Items&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Sum&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">entry&lt;/span> &lt;span class="p">=&amp;gt;&lt;/span> &lt;span class="n">entry&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Value&lt;/span> &lt;span class="p">*&lt;/span> &lt;span class="n">cart&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Value&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Prices&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">GetValueOrDefault&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">entry&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Key&lt;/span>&lt;span class="p">));&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="k">new&lt;/span> &lt;span class="n">CartSummary&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">itemCount&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">total&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">cart&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Value&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Abandoned&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">public&lt;/span> &lt;span class="kd">async&lt;/span> &lt;span class="n">Task&lt;/span> &lt;span class="n">AbandonCart&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">CancellationToken&lt;/span> &lt;span class="n">ct&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="k">default&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">var&lt;/span> &lt;span class="n">cart&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="k">await&lt;/span> &lt;span class="n">State&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">GetOrCreateAsync&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;cart&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">()&lt;/span> &lt;span class="p">=&amp;gt;&lt;/span> &lt;span class="k">new&lt;/span> &lt;span class="n">CartState&lt;/span>&lt;span class="p">(),&lt;/span> &lt;span class="n">ct&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">cart&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Value&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Abandoned&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="kc">true&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="c1">// saved once at end of turn&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Startup is one line, with no endpoint mapping and no per-actor registration:&lt;/p></description></item><item><title>Part 2: Evolving the cart's state</title><link>https://dapr.website.cncfstack.com/developing-applications/sdks/dotnet/dotnet-actors-next/tutorial/dotnet-actorsnext-tutorial-migration/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dapr.website.cncfstack.com/developing-applications/sdks/dotnet/dotnet-actors-next/tutorial/dotnet-actorsnext-tutorial-migration/</guid><description>&lt;p>The second example continues the same cart across a breaking state change. &lt;code>CartStateV1&lt;/code> stored a flat list of SKUs; &lt;code>CartStateV2&lt;/code> groups them into line items with quantities, and &lt;code>CartStateV3&lt;/code> adds a cached total. You ship each new shape with one small upcaster, and old carts fold forward on read with no data backfill.&lt;/p>
&lt;p>Code for this part: &lt;code>/examples/Actor.Next/02-Migration/&lt;/code>.&lt;/p>
&lt;h2 id="what-you-build">What you build&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-csharp" data-lang="csharp">&lt;span class="line">&lt;span class="cl">&lt;span class="kd">public&lt;/span> &lt;span class="kd">sealed&lt;/span> &lt;span class="k">class&lt;/span> &lt;span class="nc">CartStateV1ToV2&lt;/span> &lt;span class="p">:&lt;/span> &lt;span class="n">IActorStateUpcaster&lt;/span>&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="n">CartStateV1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">CartStateV2&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">public&lt;/span> &lt;span class="n">ValueTask&lt;/span>&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="n">CartStateV2&lt;/span>&lt;span class="p">&amp;gt;&lt;/span> &lt;span class="n">UpcastAsync&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">CartStateV1&lt;/span> &lt;span class="n">state&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">CancellationToken&lt;/span> &lt;span class="n">cancellationToken&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="k">default&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">var&lt;/span> &lt;span class="n">lines&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="n">state&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Skus&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">.&lt;/span>&lt;span class="n">GroupBy&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">sku&lt;/span> &lt;span class="p">=&amp;gt;&lt;/span> &lt;span class="n">sku&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">StringComparer&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Ordinal&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">.&lt;/span>&lt;span class="n">Select&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">group&lt;/span> &lt;span class="p">=&amp;gt;&lt;/span> &lt;span class="k">new&lt;/span> &lt;span class="n">CartLine&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">group&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Key&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="k">group&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Count&lt;/span>&lt;span class="p">()))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">.&lt;/span>&lt;span class="n">ToList&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">ValueTask&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">FromResult&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">new&lt;/span> &lt;span class="n">CartStateV2&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="n">Lines&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="n">lines&lt;/span> &lt;span class="p">});&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kd">public&lt;/span> &lt;span class="kd">sealed&lt;/span> &lt;span class="k">class&lt;/span> &lt;span class="nc">CartStateV2ToV3&lt;/span> &lt;span class="p">:&lt;/span> &lt;span class="n">IActorStateUpcaster&lt;/span>&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="n">CartStateV2&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">CartStateV3&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">public&lt;/span> &lt;span class="n">ValueTask&lt;/span>&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="n">CartStateV3&lt;/span>&lt;span class="p">&amp;gt;&lt;/span> &lt;span class="n">UpcastAsync&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">CartStateV2&lt;/span> &lt;span class="n">state&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">CancellationToken&lt;/span> &lt;span class="n">cancellationToken&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="k">default&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">=&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">ValueTask&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">FromResult&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">new&lt;/span> &lt;span class="n">CartStateV3&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Lines&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="n">state&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Lines&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">ToList&lt;/span>&lt;span class="p">(),&lt;/span> &lt;span class="n">TotalQuantity&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="n">state&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Lines&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Sum&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">line&lt;/span> &lt;span class="p">=&amp;gt;&lt;/span> &lt;span class="n">line&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Quantity&lt;/span>&lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">});&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>That is the entire migration: one small upcaster per shape change, and the chain composes. The source generator discovers and registers the upcasters; on read the runtime discovers whatever version is stored, folds it up to the shape your code asks for, and re-persists at the current shape lazily on the next save. Nothing in the actor branches on a version.&lt;/p></description></item><item><title>Part 3: The cart that reacts</title><link>https://dapr.website.cncfstack.com/developing-applications/sdks/dotnet/dotnet-actors-next/tutorial/dotnet-actorsnext-tutorial-pubsub/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dapr.website.cncfstack.com/developing-applications/sdks/dotnet/dotnet-actors-next/tutorial/dotnet-actorsnext-tutorial-pubsub/</guid><description>&lt;p>The third example continues the cart. An inventory service publishes &lt;code>inventory-restocked&lt;/code> events, and a cart waiting on an out-of-stock item should wake and mark it available. The subscription is declared on the actor method, and the event names which cart gets it.&lt;/p>
&lt;p>Code for this part: &lt;code>/examples/Actor.Next/03-PubSub/&lt;/code>.&lt;/p>
&lt;h2 id="what-you-build">What you build&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-csharp" data-lang="csharp">&lt;span class="line">&lt;span class="cl">&lt;span class="na">[DaprActor(&amp;#34;RestockingCart&amp;#34;)]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kd">public&lt;/span> &lt;span class="kd">sealed&lt;/span> &lt;span class="k">class&lt;/span> &lt;span class="nc">RestockingCartActor&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">ActorActivationContext&lt;/span> &lt;span class="n">context&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">:&lt;/span> &lt;span class="n">Actor&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">IRestockingCartActor&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">protected&lt;/span> &lt;span class="kd">override&lt;/span> &lt;span class="n">ActorId&lt;/span> &lt;span class="n">Id&lt;/span> &lt;span class="p">=&amp;gt;&lt;/span> &lt;span class="n">context&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">ActorId&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">protected&lt;/span> &lt;span class="kd">override&lt;/span> &lt;span class="n">IActorStateAccessor&lt;/span> &lt;span class="n">State&lt;/span> &lt;span class="p">=&amp;gt;&lt;/span> &lt;span class="n">context&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">State&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="na">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="na"> [Subscribe(&amp;#34;orders-pubsub&amp;#34;, &amp;#34;inventory-restocked&amp;#34;, RouteBy = nameof(RestockEvent.CartId))]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">public&lt;/span> &lt;span class="kd">async&lt;/span> &lt;span class="n">Task&lt;/span> &lt;span class="n">OnRestock&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">RestockEvent&lt;/span> &lt;span class="n">evt&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">CancellationToken&lt;/span> &lt;span class="n">ct&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="k">default&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">var&lt;/span> &lt;span class="n">cart&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="k">await&lt;/span> &lt;span class="n">State&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">GetOrCreateAsync&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;cart&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">()&lt;/span> &lt;span class="p">=&amp;gt;&lt;/span> &lt;span class="k">new&lt;/span> &lt;span class="n">RestockingCartState&lt;/span>&lt;span class="p">(),&lt;/span> &lt;span class="n">ct&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Delivery is at-least-once, so this must be safe to run more than once:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// removing first makes a duplicate delivery a no-op after the first success.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">cart&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Value&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">WaitingForStock&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Remove&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">evt&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Sku&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">cart&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Value&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Available&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Add&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">evt&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Sku&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The host wires these subscriptions from &lt;code>[Subscribe]&lt;/code> when you register the streams host alongside actors:&lt;/p></description></item><item><title>Part 4: The auction</title><link>https://dapr.website.cncfstack.com/developing-applications/sdks/dotnet/dotnet-actors-next/tutorial/dotnet-actorsnext-tutorial-auction/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dapr.website.cncfstack.com/developing-applications/sdks/dotnet/dotnet-actors-next/tutorial/dotnet-actorsnext-tutorial-auction/</guid><description>&lt;p>The fourth example is the live auction: open and accepting bids, with a soft-close timer that each accepted bid resets; when it fires the auction transitions to sold and marks fulfillment as started. It looks like a workflow and is not, which is exactly what we&amp;rsquo;re seeking to illustrate. This is the example where the test is unambiguously the headline.&lt;/p>
&lt;p>Code for this part: &lt;code>/examples/Actor.Next/04-Auction/&lt;/code>.&lt;/p>
&lt;h2 id="what-you-build">What you build&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-csharp" data-lang="csharp">&lt;span class="line">&lt;span class="cl">&lt;span class="na">[GenerateActorClient]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kd">public&lt;/span> &lt;span class="k">interface&lt;/span> &lt;span class="nc">IAuctionActor&lt;/span> &lt;span class="p">:&lt;/span> &lt;span class="n">IActor&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Task&lt;/span>&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="n">BidResult&lt;/span>&lt;span class="p">&amp;gt;&lt;/span> &lt;span class="n">PlaceBid&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">Bid&lt;/span> &lt;span class="n">bid&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">CancellationToken&lt;/span> &lt;span class="n">cancellationToken&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="k">default&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Task&lt;/span> &lt;span class="n">Close&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">CancellationToken&lt;/span> &lt;span class="n">cancellationToken&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="k">default&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Task&lt;/span> &lt;span class="n">Expire&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">CancellationToken&lt;/span> &lt;span class="n">cancellationToken&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="k">default&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Task&lt;/span>&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="n">AuctionState&lt;/span>&lt;span class="p">&amp;gt;&lt;/span> &lt;span class="n">GetState&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">CancellationToken&lt;/span> &lt;span class="n">cancellationToken&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="k">default&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Task&lt;/span>&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="n">AuctionData&lt;/span>&lt;span class="p">&amp;gt;&lt;/span> &lt;span class="n">GetData&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">CancellationToken&lt;/span> &lt;span class="n">cancellationToken&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="k">default&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kd">public&lt;/span> &lt;span class="kd">enum&lt;/span> &lt;span class="n">AuctionState&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="n">Open&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">Sold&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">Expired&lt;/span> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kd">public&lt;/span> &lt;span class="kd">sealed&lt;/span> &lt;span class="k">record&lt;/span> &lt;span class="nc">AuctionData&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="kt">decimal&lt;/span> &lt;span class="n">HighBid&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kt">string?&lt;/span> &lt;span class="n">HighBidder&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kt">bool&lt;/span> &lt;span class="n">FulfillmentStarted&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">public&lt;/span> &lt;span class="kd">static&lt;/span> &lt;span class="n">AuctionData&lt;/span> &lt;span class="n">Empty&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="k">get&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="p">}&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="k">new&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="m">0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kc">null&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kc">false&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kd">public&lt;/span> &lt;span class="kd">sealed&lt;/span> &lt;span class="k">record&lt;/span> &lt;span class="nc">Bid&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="kt">decimal&lt;/span> &lt;span class="n">Amount&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kt">string&lt;/span> &lt;span class="n">Bidder&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kd">public&lt;/span> &lt;span class="kd">sealed&lt;/span> &lt;span class="k">record&lt;/span> &lt;span class="nc">CloseAuction&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kd">public&lt;/span> &lt;span class="kd">sealed&lt;/span> &lt;span class="k">record&lt;/span> &lt;span class="nc">ExpireAuction&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kd">public&lt;/span> &lt;span class="kd">enum&lt;/span> &lt;span class="n">BidResult&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="n">Accepted&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">TooLow&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">Closed&lt;/span> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="na">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="na">[DaprActor(&amp;#34;Auction&amp;#34;)]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kd">public&lt;/span> &lt;span class="kd">sealed&lt;/span> &lt;span class="k">class&lt;/span> &lt;span class="nc">AuctionActor&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">ActorActivationContext&lt;/span> &lt;span class="n">context&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">IActorTimerScheduler&lt;/span> &lt;span class="n">timers&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">:&lt;/span> &lt;span class="n">StateMachineActor&lt;/span>&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="n">AuctionState&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">AuctionData&lt;/span>&lt;span class="p">&amp;gt;,&lt;/span> &lt;span class="n">IAuctionActor&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">context&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">timers&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s">&amp;#34;Auction&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">AuctionData&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Empty&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">private&lt;/span> &lt;span class="kd">static&lt;/span> &lt;span class="k">readonly&lt;/span> &lt;span class="n">TimeSpan&lt;/span> &lt;span class="n">SoftClose&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="n">TimeSpan&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">FromSeconds&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="m">30&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">protected&lt;/span> &lt;span class="kd">override&lt;/span> &lt;span class="k">void&lt;/span> &lt;span class="n">Configure&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">IStateMachine&lt;/span>&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="n">AuctionState&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">AuctionData&lt;/span>&lt;span class="p">&amp;gt;&lt;/span> &lt;span class="n">sm&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">sm&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">InitialState&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">AuctionState&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Open&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">sm&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">In&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">AuctionState&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Open&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">.&lt;/span>&lt;span class="n">On&lt;/span>&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="n">Bid&lt;/span>&lt;span class="p">&amp;gt;()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">.&lt;/span>&lt;span class="n">When&lt;/span>&lt;span class="p">((&lt;/span>&lt;span class="n">data&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">bid&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">=&amp;gt;&lt;/span> &lt;span class="n">bid&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Amount&lt;/span> &lt;span class="p">&amp;gt;&lt;/span> &lt;span class="n">data&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">HighBid&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">.&lt;/span>&lt;span class="n">Do&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="kd">async&lt;/span> &lt;span class="n">ctx&lt;/span> &lt;span class="p">=&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">ctx&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Update&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">data&lt;/span> &lt;span class="p">=&amp;gt;&lt;/span> &lt;span class="n">data&lt;/span> &lt;span class="n">with&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="n">HighBid&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="n">ctx&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Event&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Amount&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">HighBidder&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="n">ctx&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Event&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Bidder&lt;/span> &lt;span class="p">});&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">await&lt;/span> &lt;span class="n">timers&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">RescheduleAsync&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;Auction&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">Id&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s">&amp;#34;soft-close&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">SoftClose&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">nameof&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">Close&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="kt">string&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Empty&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">ctx&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Reply&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">BidResult&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Accepted&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">})&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">.&lt;/span>&lt;span class="n">Otherwise&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">.&lt;/span>&lt;span class="n">Reply&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">BidResult&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">TooLow&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">sm&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">In&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">AuctionState&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Open&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">.&lt;/span>&lt;span class="n">On&lt;/span>&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="n">CloseAuction&lt;/span>&lt;span class="p">&amp;gt;().&lt;/span>&lt;span class="n">GoTo&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">AuctionState&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Sold&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">sm&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">In&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">AuctionState&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Open&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">.&lt;/span>&lt;span class="n">On&lt;/span>&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="n">ExpireAuction&lt;/span>&lt;span class="p">&amp;gt;().&lt;/span>&lt;span class="n">GoTo&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">AuctionState&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Expired&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">sm&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">In&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">AuctionState&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Sold&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">.&lt;/span>&lt;span class="n">OnEntry&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">ctx&lt;/span> &lt;span class="p">=&amp;gt;&lt;/span> &lt;span class="n">ctx&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Update&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">data&lt;/span> &lt;span class="p">=&amp;gt;&lt;/span> &lt;span class="n">data&lt;/span> &lt;span class="n">with&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="n">FulfillmentStarted&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="kc">true&lt;/span> &lt;span class="p">}))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">.&lt;/span>&lt;span class="n">Ignore&lt;/span>&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="n">Bid&lt;/span>&lt;span class="p">&amp;gt;()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">.&lt;/span>&lt;span class="n">Ignore&lt;/span>&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="n">CloseAuction&lt;/span>&lt;span class="p">&amp;gt;()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">.&lt;/span>&lt;span class="n">Ignore&lt;/span>&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="n">ExpireAuction&lt;/span>&lt;span class="p">&amp;gt;();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">sm&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">In&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">AuctionState&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Expired&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">.&lt;/span>&lt;span class="n">Ignore&lt;/span>&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="n">Bid&lt;/span>&lt;span class="p">&amp;gt;()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">.&lt;/span>&lt;span class="n">Ignore&lt;/span>&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="n">CloseAuction&lt;/span>&lt;span class="p">&amp;gt;()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">.&lt;/span>&lt;span class="n">Ignore&lt;/span>&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="n">ExpireAuction&lt;/span>&lt;span class="p">&amp;gt;();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">public&lt;/span> &lt;span class="n">Task&lt;/span>&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="n">BidResult&lt;/span>&lt;span class="p">&amp;gt;&lt;/span> &lt;span class="n">PlaceBid&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">Bid&lt;/span> &lt;span class="n">bid&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">CancellationToken&lt;/span> &lt;span class="n">cancellationToken&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="k">default&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">CurrentState&lt;/span> &lt;span class="p">!=&lt;/span> &lt;span class="n">AuctionState&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Open&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">Task&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">FromResult&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">BidResult&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Closed&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">Raise&lt;/span>&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="n">BidResult&lt;/span>&lt;span class="p">&amp;gt;(&lt;/span>&lt;span class="n">bid&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">cancellationToken&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">public&lt;/span> &lt;span class="n">Task&lt;/span> &lt;span class="n">Close&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">CancellationToken&lt;/span> &lt;span class="n">cancellationToken&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="k">default&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">=&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Raise&lt;/span>&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="kt">object?&lt;/span>&lt;span class="p">&amp;gt;(&lt;/span>&lt;span class="k">new&lt;/span> &lt;span class="n">CloseAuction&lt;/span>&lt;span class="p">(),&lt;/span> &lt;span class="n">cancellationToken&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">public&lt;/span> &lt;span class="n">Task&lt;/span> &lt;span class="n">Expire&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">CancellationToken&lt;/span> &lt;span class="n">cancellationToken&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="k">default&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">=&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Raise&lt;/span>&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="kt">object?&lt;/span>&lt;span class="p">&amp;gt;(&lt;/span>&lt;span class="k">new&lt;/span> &lt;span class="n">ExpireAuction&lt;/span>&lt;span class="p">(),&lt;/span> &lt;span class="n">cancellationToken&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">public&lt;/span> &lt;span class="n">Task&lt;/span>&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="n">AuctionState&lt;/span>&lt;span class="p">&amp;gt;&lt;/span> &lt;span class="n">GetState&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">CancellationToken&lt;/span> &lt;span class="n">cancellationToken&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="k">default&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">=&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Task&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">FromResult&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">CurrentState&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">public&lt;/span> &lt;span class="n">Task&lt;/span>&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="n">AuctionData&lt;/span>&lt;span class="p">&amp;gt;&lt;/span> &lt;span class="n">GetData&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">CancellationToken&lt;/span> &lt;span class="n">cancellationToken&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="k">default&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">=&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Task&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">FromResult&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">Data&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="why-a-state-machine-and-where-it-ends">Why a state machine, and where it ends&lt;/h3>
&lt;p>An auction is a long-lived, addressable entity with explicit states, not a finite process, so it belongs in a state-machine actor rather than a workflow. A high rate of bids would grow a workflow&amp;rsquo;s replay history without bound, every bidder needs an instant synchronous read of the current high bid, and the soft-close behavior is a race. The transition to &lt;code>Sold&lt;/code> is where it hands off: its entry action marks fulfillment started, which is the point where a real deployment kicks off a fulfillment workflow for the finite, multi-step process (charge the winner, notify losers, arrange shipping), so the entity stays in the actor and the bounded orchestration goes to a workflow. That boundary is the thing to take away; the two compose rather than compete.&lt;/p></description></item><item><title>Part 5: Runtime-defined state machines</title><link>https://dapr.website.cncfstack.com/developing-applications/sdks/dotnet/dotnet-actors-next/tutorial/dotnet-actorsnext-tutorial-interpreted/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dapr.website.cncfstack.com/developing-applications/sdks/dotnet/dotnet-actors-next/tutorial/dotnet-actorsnext-tutorial-interpreted/</guid><description>&lt;p>The fifth example is the destination the first four were building toward: state machines that are not compiled into your app at all, but supplied as data at runtime, verified before they go live, and driven without a compile-time contract.&lt;/p>
&lt;p>The scenario is a device-management platform. You manage many kinds of devices, a smart lock, a thermostat, a valve, and each device type has its own state machine: a lock moves from Locked to Unlocking to Unlocked to Locking and back, driven by commands and sensor events. New device types are onboarded through configuration, not a code deploy, and each physical device is a long-lived, addressable entity, exactly the kind of thing &lt;a href="https://dapr.website.cncfstack.com/developing-applications/sdks/dotnet/dotnet-actors-next/tutorial/dotnet-actorsnext-tutorial-auction/">Part 4&lt;/a> argued belongs in a state-machine actor. The difference here is that the machine is data, so one compiled actor runs every device type.&lt;/p></description></item><item><title>Part 6: Composing interpreted actors with workflows</title><link>https://dapr.website.cncfstack.com/developing-applications/sdks/dotnet/dotnet-actors-next/tutorial/dotnet-actorsnext-tutorial-approvals/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dapr.website.cncfstack.com/developing-applications/sdks/dotnet/dotnet-actors-next/tutorial/dotnet-actorsnext-tutorial-approvals/</guid><description>&lt;p>The sixth example puts the interpreted runtime from &lt;a href="https://dapr.website.cncfstack.com/developing-applications/sdks/dotnet/dotnet-actors-next/tutorial/dotnet-actorsnext-tutorial-interpreted/">Part 5&lt;/a> next to a Dapr Workflow and shows the two composing. An approval document is a long-lived, addressable entity, so it is an interpreted state-machine actor whose behavior is authored as data. Settling an approved document is a finite, failure-prone process, so it is a workflow. The entity starts the workflow, and the workflow drives the entity back; each does what it is good at.&lt;/p></description></item></channel></rss>