LostKobrakai

LostKobrakai

With processes I tend to test in stages:

If the internal computation is complex then have it be handled by another module with pure functions – test those.

Then testing the statefulness of a single process. Start one process per test and assert the interface of the otherwise black box – meaning test whatever the message interface of the process is without ever looking into the process’s state. This might need some accompanying code in the implementation to adjust things like timeouts, third processes being sent messages or access to test specific resources like ecto sandbox.

And the third layer is more integration test style for starting a whole assembly of processes and asserting on their combined public interface (likely still messages). Here individual messages between processes under test are no longer relevant. Only thing counting is that the whole system does what can be asserted on from the outside.

5
Post #11
Sebb

Sebb

Most likely.

I’ll look at my code and see where this is possible. Makes sense that this is easier.

Yes, it is. But sometimes its just needed. I’m implementing a connection-oriented protocol, which has to time out after some time. Does :gen_statem make testing timers easier in any way?

Thanks for your help, I’ll refactor my code and tests with the things I learned and will be back with easier code, more tests and more questions.

0
Post #12
ityonemo

ityonemo

Ah! A connection oriented protocol. Classic use case for GenServer. I recommend using Connection. Connection — connection v1.1.0

And if you want both tcp/tls i wrote Transport (though it’s not been tested with the new ssl 1.3) Transport — transport v0.1.0

1
Post #13
Sebb

Sebb

Connection looks interesting, but it will not help, because I’m implementing a protocol stack (EN 50090 - Wikipedia), Connection builds upon an existing stack.

I just had a quick look over my Genservers and I already see some points I can simplify following your hints. I’ll be back later when thats done.

1
Post #14
ityonemo

ityonemo

Happy to help! If you prefer not making it public feel free to DM me, too. I’m in the process of making a youtube series on elixir concurrency, and i have deliberately pushed GenServers to the end, because they are tricky and I actively want to discourage people from using them, but it would be nice to know common things that people do that may or may not be the best.

2
Post #15
Sebb

Sebb

I could make the stack public, but only if I’m sure it’ll work out in the end.
Right now I’m not sure if I will complete it, I’m just looking into Elixir/BEAM to see what it can do in the embedded space. (preliminary result: it may reduce the tools and languages we use drastically)
I’ll make a minimal example out of the GenServer that is most complex.

0
Post #16
rogerweb

rogerweb

So, just double checking if a GenServer makes sense in my scenario:

I have a number of users connected to my application via websocket (Phoenix channels). A separated process consumes messages from AWS SQS (a FIFO queue) and sends each message to the target connected user. For each sent and received message the application receives an “ack” back in the channel. At that point I need to delete the message from SQS. I could call SQS’s API to delete the message right there, in-process, individually. However, it looks the best practice is to batch these deletes, sending up to 10 message IDs in one single request to SQS.

So I created a GenServer that receives a message ID via cast and appends it to a list. Once the list has 10 IDs or a timer expires after let’s say 1 second, it deletes the 10 or less messages in one go in SQS and empty the list.

Would you say it’s a fair case for a GenServer?

Is it available? I would like very much to watch it.

0
Post #17
ityonemo

ityonemo

It’s a use case for GenServers, but sounds like a better fit for Amazon SQS — Broadway v1.3.0
It’s usually better to use someone else’s GenServer :wink:

I didn’t get to GenServers in the series, but I did polish the series and give a talk on it: https://youtu.be/31W6OOVUGVs

0
Post #18
rogerweb

rogerweb

Good! Thanks for the feedback!

I do use Broadway, but unfortunately I can’t use its acknowledger because the acks are received in the channels processes asynchronously and not in Broadway’s callbacks (How to acknowledge a Broadway message asynchronously?)

0
Post #19
— All posts loaded —