Get Even More Visitors To Your Blog, Upgrade To A Business Listing >>

Gen servers - Abstracting state management and task run together

Posted on Oct 15 In Elixir, every function runs inside a separate process, and we can deal with Processes in a very natural way offered by the language. It's possible to manage state between multiple long-running processes through known abstractions such as Agent. In this article, we'll talk a little about an abstraction that allows the management of long-running processes with state and message communication for running functions accordingly! I hope it'll be fun and easy to understand.It's really important to understand what problem we're trying to solve before we even consider which implementation we should try, right? So the problem here is lack of abstraction around long running processes. Today, we can write our own Module that handles some state and implement a method that uses the receive block to create a "mailbox", or we can use simple abstractions such as Agent and Task to either hold state only or manage asynchronous tasks only.First, let's rewind a bit and understand what we do to share state in a process using simpler abstractions. If you want to know more in detail about those modules, reach out to the previous article linked at the beginning. :)The Agent module provides a simple and efficient way to manage state, personally I view this module as an data structure for the process architecture because you can control any primitive value through a pid and getters/setters. It's pretty easy to use as you can see below in the example:As you can see, we have a getter and a setter method that both accept a function callback to manage the internal state, with this simple API we can manage it just an data structure.Another abstraction that we can use with processes is the Task module that works around the idea of handling asynchronous processes (specifically abstracting the spawn function). It has a really simple API, and works like the following example:If you know languages like JavaScript or csharp, you may recall the async await syntax from them.After all this, you may be wondering why we need to use a Gen Server if we already have those modules presented above. Well, using a Gen server is similar to gluing all those concepts together (both async processes and state management) with a single and easy-to-use API and with a very important concept implemented: a mailbox for message-based architecture.A mailbox is a common term in the elixir community that describes a module that can receive messages and act on it. The common way is by using the receive block (under the hood or explicitly) to handle those messages via pattern matching and spawn another processes with the correct action to take.While using this abstraction, we're able to separate our client and server code by defining handle methods for each message and acting correctly on them. We'll see more about it below!The Gen Server abstraction provides an architecture that allows us to separate our module code into message senders and handle receivers. It's possible to either use GenServer.call or GenServer.cast with a message atom to activate a specific method via pattern matching.For example, while using the Agent module, you'll most likely keep all the logic in the same place, as shown below:Since the Agent module didn't provide enough abstraction, you're forced to provide the function that needs to take action on the state right there in the update function. But by using a message-base abstraction, we can modularize our code a lot more, like below:See? We were able to separate a lot more code by simply using the power of Elixir pattern matching and the message architecture that the Gen server provided. The usage of this abstraction is quite straightforward; you need to implement the behavior as follows:After understanding the server part, let's complement it with some client-code API for us to call on the REPL:The client code in this specific case will serve as an easy API for the external world, so we don't need to keep referring to the GenServer module always. With this set of methods we can handle sync code (the list_names method with call) and async code (the add_name method with cast) easily!Observe also that on our handle_cast for :insert we're using the timer to sleep 5 seconds on purpose!, below we'll show how this works on the REPL to understand the difference between async and sync calls.To view the correct delay, watch the below video:To refer to the methods used on the REPL:The add_name method returned instantly, but the list_names method suffered from the timer that we imposed. The balance between those two concepts turn this abstraction really useful and flexible!This is another part of the learning through processes in elixir! I hope it's useful for anyone reading this, it's been an awesome experience for me since I'm writing while learning the language and all those new concepts. If I can help with anything, just reach out ! May the force be with you 🍒Templates let you quickly answer FAQs or store snippets for re-use. Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment's permalink. Hide child comments as well Confirm For further actions, you may consider blocking this person and/or reporting abuse Davide Santangelo - Oct 13 Arindam Majumder - Oct 3 Igor Coimbra - Sep 24 Necati Özmen - Oct 12 Once suspended, cherryramatis will not be able to comment or publish posts until their suspension is removed. Once unsuspended, cherryramatis will be able to comment and publish posts again. Once unpublished, all posts by cherryramatis will become hidden and only accessible to themselves. If cherryramatis is not suspended, they can still re-publish their posts from their dashboard. Note: Once unpublished, this post will become invisible to the public and only accessible to Cherry Ramatis. They can still re-publish the post if they are not suspended. Thanks for keeping DEV Community safe. Here is what you can do to flag cherryramatis: cherryramatis consistently posts content that violates DEV Community's code of conduct because it is harassing, offensive or spammy. Unflagging cherryramatis will restore default visibility to their posts. DEV Community — A constructive and inclusive social network for software developers. With you every step of your journey. Built on Forem — the open source software that powers DEV and other inclusive communities.Made with love and Ruby on Rails. DEV Community © 2016 - 2023. We're a place where coders share, stay up-to-date and grow their careers.



This post first appeared on VedVyas Articles, please read the originial post: here

Share the post

Gen servers - Abstracting state management and task run together

×

Subscribe to Vedvyas Articles

Get updates delivered right to your inbox!

Thank you for your subscription

×