slashmili

slashmili

Design a library with async callbacks

I have a question about code design in Elixir.

I’m writing a library that works with bluetooth and I want to make it general so developers can customize based on their own use case .

An example behaviour is when a new device is discovered, I want to notify the user’s code that a new device is discovered.

So I have few approaches but I’m not happy with any of them.

1: using message passing between processes

defmodule Bluetooth do
  def start_discovery(handler_pid) do
    #....
    #eventually will send a message to `handler_pid` when a device is discovered
    #ex: send(handler_pid, {:device_discovered, device})
    :ok
  end
end

This looks fine if only I could have a behaviour like this

defmodule BluetoothDiscovery do
  @callback handle_info({:device_discovered, any}, any) :: any
end

This way users that implement the code explicitly know to implement this function.
I can technically use this but looks weird and compiler won’t complain about missing function if I have another handle_info in my module for example:

defmodule MyBluetoothDiscovery do
  use GenServer
  @behaviour BluetoothDiscovery
  def handle_info(:timeout, state) do
  end
end

2: using function callbacks

defmodule Bluetooth do
  def start_discovery(handler_module) do
    #....
    #eventually will call device_discovered function on handler_module
    #ex: apply(handler_module, :device_discovered, [device])
    :ok
  end
end

Now I can define a behaviour and ask users to implement it

defmodule BluetoothDiscovery do
  @callback device_discovered(device) :: atom
end

This time the compiler gives me warning if I missed the implementation

defmodule MyBluetoothDiscovery do
  use GenServer
  @behaviour BluetoothDiscovery
  def device_discovered(device) do
    #handle new device
  end
end

This also looks fine but reminds me of interfaces in OOP land.

Do you have any suggestion?

Most Liked

OvermindDL1

OvermindDL1

What I do is:

  • If the user should always handle the callback in their own process so they cannot screw up ‘my’ process in any way (like exceptioning and such) or if they might take a while, then send a message.
  • If the user is generally fast or just want them to handle it inline, faster, or let them send their own message then I use a behaviour.

:slight_smile:

Where Next?

Popular in Questions Top

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
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
mgjohns61585
Could someone help me? I’m making my first elixir program, number guessing game. I can’t figure out how to convert the user’s guess from ...
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
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
vac
Hi, I’m quite new in Elixir and I’m trying to format a string to a PEM format. I have the certificate value like MIIDBTCCAe2...... and I...
New
ycv005
I have followed this StackOverflow post to install the specific version of Erlang. And When I am running mix ecto.setup then getting fol...
New
stefanluptak
Hello everybody, usually, I use a 29" ultra-wide monitor for VSCode which can easily accomodate explorer (files panel) + file with code ...
New
RisingFromAshes
I’ve read in another post that it may be possible with a router helper - but I couldn’t find an appropriate one, and tbh, I’m still just ...
New
dblack
I’ve got an issue with an app and I’ve no idea of how to troubleshoot it. I’m hoping someone here might have seen something similar. I p...
New

Other popular topics Top

chrismccord
As promised, the first release candidate of Phoenix 1.3.0 is out! This release focuses on code generators with improved project structure...
New
JeremM34
Hello, how can I check the Phoenix version ? Thanks !
New
aesmail
Hello guys, I have finally made it. I created an admin interface for a framework. It’s been on my todo list for years and with the curre...
New
joeerl
Hello again - after a longish gap I’ve decided I really must dig into Elixir and see what’s been happening here - so I have a few questio...
New
pmjoe
I have a relationship of love and hate with Elixir. Lots of things are just absolutely right, but there are some things that are kind of ...
New
Emily
I have VueJS GUIs with the project generated using Webpack. I have Elixir modules that will need to be used by the VueJS GUIs. I forese...
New
AstonJ
Please see the new poll here: Which code editor or IDE do you use? (Poll) (2022 Edition) It’s been a while since we first asked this, I...
208 31142 143
New
ashish173
I am using Ecto timestamps with postgres, I can see the timestamps() use the :naive_dateime but for my use case I wanted to store the ti...
New
openscript
Hello! Sorry for this astonishing simple question, but I’m really stuck. I try to set up the intellij-elixir plugin, but I don’t know ho...
New
hariharasudhan94
Lets say I have map like this fetching from my database %{"_id" => #BSON.ObjectId<58eb1a7a9ad169198c3dXXXX>, "email" => ...
New

We're in Beta

About us Mission Statement