benonymus

benonymus

How to keep track of potentially 1000s of events participant cap's change?

Hey there,

I have the following problem:
I have events in my database, a lot of them, and the list will only grow.
Every event can have multiple ticket types, and each ticket type has a quantity field.
The sum of the quantity fields for given event’s ticket types is the participant cap.

I want to introduce a waiting list option so if a spot frees up for any reason, being someone leaving or the total participant cap growing I want to send an email to the users on the waiting list.

How do I keep track of the change of the participant cap?

I could create just a function that accepts 2 instances of an event and compare the participant cap, so I can pass it one event being before any action and one after and if the part cap is changed then send the emails.
cons for this is that it is very manual, need to find the places where it is relevant in the code, pro is that it is pretty simple.

Other option could be to have a genserver for each event, keeping the current participant cap for each event, and tracking if messages have already been sent or not. Maybe using:
https://elixirschool.com/blog/til-genserver-handle-continue/
But isn’t this approach very wasteful?
Also somehow would need to make sure that every events has a genserver running, even new ones that get inserted.

Any thoughts on ether of the approaches? Maybe other ideas?

Thanks!

Marked As Solved

benonymus

benonymus

Okay, I ended up implementing the Postgres notifications approach mostly based on this article:

It seems surprisingly good so far!

Thanks everyone for the messages!

Also Liked

chouzar

chouzar

It sound like you could take advantage of both approaches.

If all you need to achieve the task is procedural code maybe you don’t need a GenServer:

def compare(event_1, event_2), do: send_email("email")

But you would need to have received both events to execute this function. If events come and go at different times you could use laziness to defer computation:

def lazy_compare(event), do: 
  (fn later_event -> compare(event, later_event) end)

And just wait until your next input is ready so you can execute the returned function at a later time.

If you really don’t need the GenServer, yes it is a wasteful (but cheap) approach. A GenServer would be a solution to handle asynchronous calls; just be careful because you may already have this in the form of a Phoenix Server, HTTP Request or iex session, but if you’re creating your custom “subscription / publish” mechanism a GenServer would be a great way to go.

If you haven’t, I suggest you read the to spawn or not to spawn article by @sasajuric; it may help to re-arrange some thoughts on when and where to use processes.

riebeekn

riebeekn

btw, if you end up going the Postgres notifications route, I found this article (and the other article the author links to) useful in getting an initial handle on how notifications work: https://medium.com/@kaisersly/postgrex-notifications-759574f5796e

chouzar

chouzar

Sounds a lot like CQRS, and to be honest that kind of pattern really falls outside my area of expertise :grin:.

But if you would like a separate entity to take care of the handling would Task.Supervisor or DynamicSupervisor work for you? That way you would could spawn a process “on request”.

chouzar

chouzar

Definetly.

Ok, so I think I’m starting to have a clearer picture of the approach you want. When an event “goes live” you would like to track its capacity in real-time.

Thinking in “logical terms” here I think if its just 1 or multiple GenServers makes no difference. The purpose of this entity is to track 1 or multiple event caps.

Having multiple GenServers would give you reliability per event in case of failure (assuming you’re not storing on disk or a database, a process crash would lose the tracked event cap). And it may be also an optimization (or not) because you’re taking better advantage of available resources.

chouzar

chouzar

I just noticed a similar threath at Should I use GenServer for this? - #5 by lucaong :grin:

Yeah, so with a GenServer you could “poll the database” each x seconds to keep track of current state.

You could keep a “cache” whenever the cap changes (so you would change it in the database, but would also keep it in memory for real-time purposes). But this sounds clumsy if you have the database at hand.

Where Next?

Popular in Questions Top

senggen
Erlang/OTP 25 [erts-13.2.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] 15:22:35.803 [error] gen_event {lager_file_backend...
New
jerry
Good day to you all. I have been struggling to get a query involving like and ilike to work. Can anyone assist me on this, please? pro...
New
fireproofsocks
I’m working on defining a simple Ecto schema for a table (in PostGres), but I don’t see where I can define a column as NOT NULL. Conside...
New
polypush135
As many of you may have realized by now (sorry for all the posts here) I’ve been working on a db problem where I’m trying to aggregate a ...
New
vertexbuffer
Hello, can anybody help here..? I have a list of players and I what to delete an element, but every for loop the list is reverting to ori...
New
lastday4you
I wanted to check elixir version in phoenix because i found that my elixir is 1.5 but when i use Enum.chunk_by it said the function is un...
New
makeitrein
Hey all, just started picking up Elixir last week and am writing a scraper as a learning project. Baby step #1 is extracting the number ...
New
johnnyicon
Hi all, I've just started learning Elixir and Phoenix Framework, so please pardon my n00bness at this stage. I'm trying to use Postg...
New
9mm
I am constructing a JSON object (map) and I need to conditionally set a field. I’m trying to write proper elixir-way code… and I’m at a l...
New
skosch
To my knowledge, put_in, Map.update etc. all have the one limitation of not automatically creating intermediate keys when needed (for exa...
New

Other popular topics Top

Brian
What is the proper way to load a module from a file in to IEX? In the python world, doing something like this pretty standard: from ....
New
senggen
Erlang/OTP 25 [erts-13.2.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] 15:22:35.803 [error] gen_event {lager_file_backend...
New
sergio
In Ruby, I can go: User.find_by(email: "foobar@email.com").update(email: "hello@email.com") How can I do something similar in Elixir? ...
New
yawaramin
In the Dialyzer docs ( http://erlang.org/doc/man/dialyzer.html#requesting-or-suppressing-warnings-in-source-files ), there is a way to tu...
New
vertexbuffer
Hello, can anybody help here..? I have a list of players and I what to delete an element, but every for loop the list is reverting to ori...
New
freewebwithme
Using vs code and installed ElixirLS: support and debugger. And I got an error popped up on start up says Failed to run ‘elixir’ comma...
New
danschultzer
None of the current solutions worked well for me, so I went ahead and built a user management system from scratch. This project took far...
548 27727 240
New
shahryarjb
Hello, I have map which I want to convert it to string like this: the map: %{last_name: "tavakkoli", name: "shahryar"} the string I ne...
New
Qqwy
Original source of discussion: This topic on the Pragmatic Programmers' Functional Web Development with Elixir, OTP, and Phoenix forum. ...
New
Nvim
Elixir appears to be a superior language to Python. I don’t see any advantage of Python over Elixir. Are there any?
New

We're in Beta

About us Mission Statement