Outgoing middleware for Proto.Actor

blov · · 461 次点击    
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
<p>In Proto.Actor (<a href="https://github.com/AsynkronIT/protoactor-go">https://github.com/AsynkronIT/protoactor-go</a>) we have incoming middleware support, that is, incoming messages go through a middleware chain before reaching the inner Receive func.</p> <p>We are discussing adding &#34;outgoing&#34; middleware too. So that when an actor is sending messages, we could add middleware to process the outging messages.</p> <p>The reason for this is that it will allow us to add support for tracing, e.g. Zipkin. And easier testing where we can test if an actor have sent a specific message.</p> <p>To send a message, we have the concept of a &#34;PID&#34; Process ID, much like Erlang. On a PID, you can call Tell. e.g. PID.Tell(message)</p> <p>Just to clarify, the PID is like a phonenumber or email address and the message is the payload you want to send there.</p> <p>Now in order to make it possible to support tracing, we need to be able to read incoming message headers, and apply new outgoing message headers.</p> <p>a typical Receive method looks like this:</p> <pre><code>func (state *myState) Receive(ctx actor.Context) { //do stuff with ctx.Message() } </code></pre> <p>if we do:</p> <pre><code>func (state *myState) Receive(ctx actor.Context) { ...stuff somePID.Tell(outgoingMessage) } </code></pre> <p>There is no way to take the metadata, e.g. message headers from <code>ctx</code> and apply it to the outgoing message.</p> <p>To support this, we would either need to do:</p> <pre><code>func (state *myState) Receive(ctx actor.Context) { ...stuff ctx.Tell(somePID, outgoingMessage) } </code></pre> <p>Here we have moved the Tell method onto the context. this way, the Tell method could read message headers from the context and modify the outgoing message. The main issue with this one, is that it will force some MAJOR breaking changes to our users.</p> <p>Another alternative is:</p> <pre><code>func (state *myState) Receive(ctx actor.Context) { ...stuff somePID.Tell(outgoingMessage, ctx) } </code></pre> <p>In this case we have added an extra argument to Tell, so that the current context can be passed to the Tell method. This way, Tell could internally fetch middleware and message headers from ctx.</p> <p>A third alternative would be to not support outgoing middleware at all in the core lib, but rather add some sort of &#34;MessageProducer&#34; abstraction in a separate package.</p> <pre><code>func (state *myState) Receive(ctx actor.Context) { ...stuff p := producer.FromContext(ctx) somePID.Tell(p.Produce(outgoingMessage)) } </code></pre> <p>This last alternative have the least impact on our core lib, but at the same time, there would be no &#34;out of the box&#34; support for tracing, you would have to inform users how to add this. </p> <p>Thoughts, pros, cons with the different approaches?</p> <hr/>**评论:**<br/><br/>AriesDevil: <pre><p>I like the 2nd solution, but would you consider add a new method &#39;somePID.TellWithContext(outgoingMessage, ctx)&#39;</p></pre>

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

461 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传