An in-memory debit/credit wallet application. This does not include transaction semantics between user wallets.
This repo is a coding exercise submitted as a requirement for a job application to gauge software design and engineering skills in Elixir.
- Satisfy the following API
@doc """
Start a linked and isolated supervision tree and return the root server that
will handle the requests.
"""
@spec start :: GenServer.server()
@doc """
Create non-existing users with currency as "USD" and amount as 100_000.
It must ignore empty binary `""` or if the user already exists.
"""
@spec create_users(server :: GenServer.server(), users :: [String.t()]) :: :ok
@doc """
The same behavior is from `POST /transaction/bet` docs.
The `body` parameter is the "body" from the docs as a map with keys as atoms.
The result is the "response" from the docs as a map with keys as atoms.
"""
@spec bet(server :: GenServer.server(), body :: map) :: map
@doc """
The same behavior is from `POST /transaction/win` docs.
The `body` parameter is the "body" from the docs as a map with keys as atoms.
The result is the "response" from the docs as a map with keys as atoms.
"""
@spec win(server :: GenServer.server(), body :: map) :: map
- Debit and credit operations must be idempotent; there is a
transaction_uuid
included in every request to help with this - Duplicate requests (all same parameters) must return same response as original
- Duplicate requests (different param but reuse transaction_uuid) must return an error
- Debit requests that have larger amount than current balance must return an error
- Debit and credit requests must be made against same currency, in this exercise only
USD
- In cases of failed requests for (5)-(7), the client is free to reuse
transaction_uuid
and the implementation must be able to handle such scenario - Must be performant and handle 80% correctness and load testing done by the submission review
Exwallet.Root
startsExwallet.Transaction.Registry
,Exwallet.User.Registry
andExwallet.Partitioner
under a Supervisor.Exwallet.Partitioner
supervises a set of DynamicSupervisors which in turn handles a dynamic set ofExwallet.User
GenServers.
- For every user,
Exwallet.Root
finds the appropriate DynamicSupervisor viaExwallet.Partitioner
and issues request to create aExwallet.User
under it with a name registered toExwallet.User.Registry
.
Exwallet.Root
checksExwallet.Transaction.Registry
if a previous transaction with the same transaction_uuid has already been processed and if found, returns the recorded response synchronously.
- Otherwise, the
Exwallet.Root
issues an asynchronous message toExwallet.User
, withExwallet.User
replying directly to the client (not pictured here) once it's processed the transaction.