RooSoft
We have a lib that exports two functions:
Lib.connect(ip, port)simply calls:gen_tcp.connect(to_charlist(ip), port, [:binary])Lib.subscribe(socket)uses:gen_tcp.send(socket, "init")and expects the server to start sending various messages over time. That data is rather cryptic and needs to be processed by the lib so that the lib’s client can process it easily.
Let’s say that the lib’s calls were encapsulated in a GenServer, we would have an easy solution: create a handle_info/2 function, process the data and send it to a pub/sub.
Now, we think a GenServer would cause a whole lot of unnecessary complexity, so we’re trying to avoid it.
What’s the best way to make sure the lib gets the messages and sends the processed version to the clients back without blocking any of the client’s process?
Trending in Questions
I’m working on a project that simulates the bumbl example in the programming phoenix book. It acts almost like an email client. We have a...
New
Hello!
Could someone please give me a help/sample code, how to delete a file from s3 using waffle/waffle_ecto from Phoenix app.
I creat...
New
I’m seeing that a list inside a Kino.DataTable will be interpreted as a charlist, even if the Kino.configure() is set to charlists: :as_l...
New
So my question is quite simple and i have found no conclusive answer on forum, google or AI.
Should we use :erlang.float for Integer to ...
New
Hi, I’ve just set up an application with ash_authentication. There is only magic link strategy for now, so there is no confirmation add o...
New
If a change or preparation module uses Ash.Changeset.get_argument/2 or Ash.Query.get_argument/2 (or any of the other get_argument functio...
New
I’m trying to set up Emacs with elixir-ls via lsp-mode and credo via Flycheck. This should mostly be preconfigured as Flycheck picks up c...
New
Other Trending Topics
I am happy to introduce the very α version of the new programming language compiled to BEAM.
Welcome Cure.
It has literally three kille...
New
Hobbes is a low-level distributed database for the Elixir programming language.
Hobbes provides a simple, safe, and scalable storage lay...
New
Hi there! We created Gust: A task orchestrator inspired by Airflow.
For those who have never heard about Aiflow, it’s a Python-based wor...
New
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
Xamal is a deployment tool for Elixir apps that deploys native releases to bare metal servers over SSH. It’s a port of GitHub - basecamp/...
New
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge & Solve.
They are GUI (Emerge) and State management (S...
New
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #library
- #deployment
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #elixirconf
- #channels
- #exunit
- #discussion
- #code-sync
- #podcasts
- #javascript
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixirconf-us
- #blog-post
- #elixir-ls
- #ai
- #phoenix_html
- #iex
- #graphql
- #genstage
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #hex
- #security
- #metaprogramming










Showing Posts 1 to 8- Show Best Posts
- Show All (oldest first)
- Show All (newest first)
hst337
What are you talking about?
Why is that? Consider http clients for example. Using any library with processes is much easier than implementing
mintmessage handling.So, I’d suggest to create a process for this, it’ll be easier to use and this can always be optimized later in case you find an extra process a bottleneck you can’t afford (but I think you won’t).
Anyway, if you don’t want to you can take this genserver approach, you can just have something like this
I’d suggest to take a look at Mint to see how they handle it there.
But I’d still consider using processes
derek-zhou
If you don’t want to use GenServer you can just spawn on the spot and remember the client’s pid for sending back the data.
RooSoft
Well, I might be wrong. Hence the forum message.
The real use case is a tad more involved. This service, while encapsulated by the lib and now easier to use, still returns pretty raw data, message contents should be kept as is. It could be seen as the data layer in a three tier app.
Another lib would be responsible for business logic and further data refinement. The programmer using these libs shouldn’t have to care or even know about the data lib, but keep focus on the business logic one.
If the data lib has a GenServer, I don’t think there’s any way around the fact that the business logic lib should also have one. This is to prevent details about the data lib to filter through. In that case, the business logic GenServer should be responsible for the data lib GenServer and thus may end up being a Supervisor, I guess.
Nevertheless, in this situation, there are 3 processes at a minimum: the inner lib, the business logic lib, and the program itself.
This situation could be the way to go… but it still has several implications. One that bothers me is the fact that data would have to be copied twice before it gets in the program’s process. Might slow things up for larger chunks of data…
I am just wondering about best practices to architect such a thing and am very interested in what the community thinks about it.
RooSoft
Not a bad idea, and that would fix the copying problem mentioned in the post above.
We are unsure about the ease of use of the said lib, though…
Any experienced elixir system architect’s opinion would be welcome here.
hst337
I don’t understand a word you’re saying. Let’s start with something simple
What are you trying to acheive? And what API do you want to provide?
RooSoft
The data comes from an Electrum RPC endpoint, which is what most Bitcoin wallets use to transact.
For instance, the blockchain.scripthash.subscribe is mostly what I am talking about. So, the data lib I was talking about would connect to this endpoint and make sure it subscribes to a specific
scripthash.But what’s a
scripthash???It’s jargon that Bitcoin wallet devs might not want to deal with. In other words, it’s another representation of an
address. This call, in short, returns transactions relative to a specificBitcoin addressas they happen.The goal here is to not only enable devs to connect to this thing, but make it easy and relatable. Ideally, they’d just initiate a connection, passing an
IPand aportand then subscribe to a specificaddress. This is, of course, in the Bitcoin layer lib’s language. Under the hood, it would handle the electrum lib and isolate the dev from all thescripthashgibberish we initially talked about. Not to mention there’s some data conversion involved in the process.Why not combine both in a single lib, you might ask… because the raw Electrum lib
hst337
From what you wrote I can see that you want to different libraries:
So I can see 3 layers in this program
The connection management
Alright, I’ve read the python library and I can see that these RPC calls operate over some state (
SessionManagerclass holds global state of all sessions, and connection to aPeerManagerwhich maintains TCP connection to max 8 peers). And you’ll need to handle this state somehow. In erlang and elixir world we use processes for that.And there are two options for the process. You can make it a global singleton, or a local process. If you want to maintain exactly the same API as in ElectrumX, you’ll need to create a named singleton process. But I’d suggest making library more flexible and isolating process names from it. So, I’d go with
SessionManageras aSupervisormodule which startsDynamicSupervisor,Registryand startsElectrumConnectionprocesses under theDynamicSupervisor. ThisSessionManagercan take a name during the start. EachElectrumConnectionholds connection to one peerAnd the module would provide these functions
SessionManager.add_peer(session_manager_pid, peer_opts)to add a peer. This will start the new connection process under the dynamicsup, name it in the registry.SessionManager.connect_peer(),SessionManager.disconnect_peer, etc. for peer managementSessionManager.pick_connection()– randomly picks one connection (you can chose different strategy)SessionManager.execute(connection, operation, reply_to)– this one just passes an Electrum operation to the connection process which should send the result toreply_topidThis is basically how the process pool operates. I can suggest you to take a look at libraries like
poolboyElectrum JSONRPC
This part of the system is a thing that you wanted to be a process-less library for just parsing and handling responses. The problem with your approach was that you wanted it to be somehow coupled with tcp connection, which is a bad way to go.
I’d suggest spliting this into two things:
Converting elixir structure for operation into the binary with jsonrpc request/response in it. This is a pretty straightforward thing to write. You can use any data validation library you prefer, but I don’t see any problem in hand-rolling this.
Sending and receiving data over TCP as a JSONRPC spec defines. This was already done in libraries like this: GitHub - fanduel-oss/jsonrpc2-elixir: JSON-RPC 2.0 for Elixir · GitHub
Highlevel user interface
Just create something like
Electrum.subscribewhich internally calls already started globalSessionManagerand awaits the responseRooSoft
I appreciate the answer, thanks!
Just one detail… there are no peer in the problem. We just subscribe to a server and want to manage realtime data that comes out of it.
The solution we’re about to do is pretty much what you said in the beginning. We will probably keep the GenServer in the electrum lib and use a Supervisor in the business logic lib. That would allow the business logic lib to connect to other GenServers in the same way, including a potential wrapper around Bitcoin Core.