Help.com backend project by Jhorlin De Armas
Acceptance Criteria
Your program should demonstrate the following as well as demonstrate good coding practices.
- Connect and log into the system.
- Handle heartbeats appropriately and depict the reconnection logic if you do not receive a heartbeat.
- Handle input from STDIN so your user can manually send JSON data to the server process.
- Receive responses only for requests your client sends.
- Verify and validate input to be sent, and also handle errors sent by the server.
- If the random number sent back from the result of the "time" call is greater than 30, it should print out a message saying so.
- Provide a way to send both the "count" and "time" calls to the worker process and show the results in a nicely formatted way.
Usage
To test run $ npm test
To run use $ help-tcp <username>
###My solution.
I decided to solve this problem using FRP specifically rxjs.
I chose this patter because I felt it fit this use case well and allwed me to play with FRP, which I don't
get to do as much as I would like.
The basic idea is to create a stream from a tcp connection. By default sources are replayed so I needed
to make this a sharable stream, this means that any subscriber will get notified of what is happening live and not
get a replay. This also allowed me to keep track of subscribers. In this example the subscribers were the heartbeat and
any active request. When there were no more subscribers I cold close the connection. The tcp
takes in two arguments, a function to create a stream (this will happen on the first subscription only) and a function called when
there are no more subscriptions. Create
destroy.
This works really well because we can now create a heart beat subscription
based on our tcp source. Now that we have a stream we can filter out any matches for hearbeat and set a timeout. We can
also conditionally retry for a TimeoutError
. The retry logic works because if there is an error, the heartbeat subscription
is unsubscribed. Once there are no more subscriptions we will remove the client then immediately create a new one.
Also since we are handling our async through streams we can do the same for our commands. We create a source from an
EventEmmiter and when we create a client we
subscribe to the event source and pump messages into that client.
###Thoughts I chose to set a timeout on the command source/observable so that there are no lingering requests since the cli waits for a selecton before you can chose a different one. This limitation is just for cli simplicity. Since each command is it own subscription based on a the tcpSource each subscription monitors the same tcp source but the filter is not shared. This solution can multiplex many commands from one tcp connection and each command will have its own error, depending on how far down stream that error is. Parsing errors will only effect that command while tcp errors will propagate to all commands. Also each command can complete in any order irrelevant of request order.