{"authors":[{"name":"Mayuresh Waykole","url":"https://mayureshwaykole.com/"}],"description":"Engineering writing by Mayuresh Waykole on distributed systems, observability, reliability, and AI engineering.","favicon":"https://mayureshwaykole.com/favicon-32x32.png","feed_url":"https://mayureshwaykole.com/tags/event-driven-architecture/feed.json","home_page_url":"https://mayureshwaykole.com/","icon":"https://mayureshwaykole.com/apple-touch-icon.png","image":"https://mayureshwaykole.com/images/social-preview.png","items":[{"authors":[{"name":"Mayuresh Waykole"}],"content_html":"\u003ch1 id=\"events\"\u003eEvents\u003c/h1\u003e\n\u003cp\u003eIn this post, we will explore what events are, how they are used and the advantages. Throughout the post we will build our way up to a complete event driven program.\nWe will use python do this, since python has no inherent way to handle events we need to build everything from scratch.\u003c/p\u003e\n\u003ch3 id=\"events-1\"\u003eEvents\u003c/h3\u003e\n\u003cp\u003e\u003ccode\u003eEvents\u003c/code\u003e in the simplest terms are notifications.\nSoftware written such that it largely relies on events for communication is said to be \u003ccode\u003eEvent Driven\u003c/code\u003e\u003c/p\u003e\n\u003cp\u003eThe most common operations to do with an event are\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eListen\u003c/li\u003e\n\u003cli\u003eEmit\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eA program that would like to take some action when an event has occured, \u003ccode\u003elistens\u003c/code\u003e for that event.\u003c/p\u003e\n\u003cp\u003eA program \u003ccode\u003eEmits\u003c/code\u003e an Event when it would like to notify that some change has occured.\u003c/p\u003e\n\u003cp\u003eLets start with a bare bones structure with nothing but the method definition\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Events.py\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003edef\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eemit\u003c/span\u003e(event):\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e# doSomething\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003edef\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003elisten\u003c/span\u003e(event):\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e# doSomething\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eBelow is the test code. This will be used to run the Events that we write and test it.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# events.test.py\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003eimport\u003c/span\u003e Events \u003cspan style=\"color:#66d9ef\"\u003eas\u003c/span\u003e E\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Does nothing yet.\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Expectation: to be triggered when the event occurs.\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eE\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003elisten(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;FIRST_EVENT\u0026#39;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Does nothing yet.\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Expectation: to trigger the listener.\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eE\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eemit(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;FIRST_EVENT\u0026#39;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eNow that we have the general structure of the code, lets define the behaviour.\u003c/p\u003e\n\u003cp\u003eEvents are supposed to facilitate real time communication.\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003e\u003ccode\u003eThe execution flow is defined by the events\u003c/code\u003e\u003c/p\u003e\u003c/blockquote\u003e\n\u003cp\u003eWhat this means is that any listener listening on \u003ccode\u003eFIRST_EVENT\u003c/code\u003e will be triggered when that event is emitted. To do this, our listeners have to first let us know what they are listening on. Usually, the listener wants to run some code when an event occurs. This code can be put in a function, referred to as a \u003ccode\u003ecallback\u003c/code\u003e\u003c/p\u003e\n\u003cp\u003eUpdating our test to reflect the callback\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# events.test.py\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003eimport\u003c/span\u003e Events \u003cspan style=\"color:#66d9ef\"\u003eas\u003c/span\u003e E\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# callback function\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003edef\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eprintData\u003c/span\u003e():\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    print(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;an event occured\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# when event occurs, call printData\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eE\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003elisten(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;FIRST_EVENT\u0026#39;\u003c/span\u003e, printData)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# send event\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eE\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eemit(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;FIRST_EVENT\u0026#39;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# \u0026gt; an event occured\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# sends event\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eE\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eemit(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;SECOND_EVENT\u0026#39;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# \u0026gt; \u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eThe test code when run with the events library should print \u0026ldquo;an event occured\u0026rdquo; when the FIRST_EVENT is sent. However when the SECOND_EVENT is sent, nothing should happen since there is no one listening to the second event.\u003c/p\u003e\n\u003cp\u003eLets look at the \u003ccode\u003eevents.py\u003c/code\u003e implementation to see if we can make it behave as expected in the test.\u003c/p\u003e\n\u003cp\u003eThe first thing we need is to map events to listeners.\n\u003ccode\u003eAn event can have multiple listeners.\u003c/code\u003e\u003c/p\u003e\n\u003cp\u003eSo a good data structure to use will be a HashMap/Dictionary in python.\nThe key will be the event and value will be a list of callback functions.\nIt should look something like this\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;EVENT1_NAME\u0026#39;\u003c/span\u003e: [\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003elistener1 callback\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003elistener2 callback\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eHere we do the core implementation of listening to an event.\nThe code comments provide a detailed explanation of whats happening\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Events.py\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# dictionary. key = Event, value = list of callbacks\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eEventListenerMap \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e {}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;\u0026#39;\u0026#39;\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003eThe callback is added to list for an event\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;\u0026#39;\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003edef\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003elisten\u003c/span\u003e(event, callback):\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e# if its a new event, initialize a list\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e event \u003cspan style=\"color:#f92672\"\u003enot\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003ein\u003c/span\u003e EventListenerMap:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        EventListenerMap[event] \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e []\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e# add callback function to list of listeners for that event\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    EventListenerMap[event]\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eappend(callback)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;\u0026#39;\u0026#39;\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003eRuns all the callback functions for that event\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;\u0026#39;\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003edef\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eemit\u003c/span\u003e(event):\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e# get list of callback for event\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    listeners \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e EventListenerMap\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eget(event)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e# If theres atleast one listener\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e listeners \u003cspan style=\"color:#f92672\"\u003e!=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eNone\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e# iterate over list and call the function \u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e# passed by the listener\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e callback \u003cspan style=\"color:#f92672\"\u003ein\u003c/span\u003e listeners:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            callback()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eThis gives the basic implementation of our event library.\u003c/p\u003e\n\u003cp\u003eLive code can be seen here \u003ca href=\"https://repl.it/@MayureshWaykole/events-Basics\"\u003ehttps://repl.it/@MayureshWaykole/events-Basics\u003c/a\u003e\u003c/p\u003e\n","date_modified":"2019-05-01T22:12:03Z","date_published":"2019-05-01T22:12:03Z","id":"https://mayureshwaykole.com/posts/events/","image":"https://mayureshwaykole.com/images/social-preview.png","summary":"Learn event-driven programming patterns in Python. A practical guide to implementing custom event systems with code examples.","tags":["Python","Events","Event-Driven Architecture"],"title":"Events","url":"https://mayureshwaykole.com/posts/events/"}],"language":"en","title":"Event-Driven Architecture | Mayuresh Waykole","version":"https://jsonfeed.org/version/1.1"}