Skip to content

Instantly share code, notes, and snippets.

@tjconcept
Last active September 21, 2018 10:57
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tjconcept/d8358200287208a2913a0ba3f9f5972a to your computer and use it in GitHub Desktop.
Save tjconcept/d8358200287208a2913a0ba3f9f5972a to your computer and use it in GitHub Desktop.
Velocity service

The goal is a service that will monitor payments and their status (success/failure) and provide health indicators of the payment network.

It will serve as the backend behind a dashboard showing the status of some selected parties, e.g. depending on your country or preferred payment method you will see indicators for relevant networks.

The dashboard or API for it is not part of the task.

The health indicator is binary: healthy or degraded.

Each payment is delivered to the service in real-time as an event of the following format:

{
  type: 'payment',
  created: '2018-09-12T22:45:03.580Z',  // parsable by `Date.parse`
  parties: [<String|unique ID>],
  success: Boolean,
}

The parties key is a list of strings with IDs, one for each party involved in processing the payment, such as a card network or a bank.

Some parties have few payments, some many, some operate at high success/failure rates, and some at low ones. The ratio and count also varies over the course of a day, week, month and season.

To keep things simple, we will determine healthy vs. degraded depending on whether a successful payment for the party has happened within a given time interval called the "reaction time". The name is so because this is the maximum time the service will need to detect a failure.

The "reaction time" should be specific for each party, to accomodate for different velocities. The "reaction time" should be adjusted continously based on velocity to accomodate for day/night patterns, etc.

A concrete algorithm could look like:

  • Count successful payments for each party
  • Once we reach 10 for the first time, use the time from boot to now as initial "reaction time" for this party
  • Whenever a "reaction time" has passed
    • If we've counted zero, deem "degraded" and reset "reaction time" (count to 10 again)
    • If we've counted at least 1 deem "healthy"
    • If we've counted at least 1 but less than 10, double "reaction time"
    • If we've counted more than 20, half "reaction time"

The service should be able to answer about the health of a specific party. A such request will be delivered as an event and the response should be an event too.

To receive and send events a "network" (distinctive from "payment network") package is injected into the service. It is required and configured using environment variables in production but should be mocked for test purposes and is therefore not provided.

The interface is:

network.createSource() // → pull-stream source of real-time events

network.respond(sourceEvent, event)
// send an event to the origin of any event

The service should not use a database or other persistent storage.

This task has two milestones:

  1. Considerations, assumptions and planning
  2. Implementation

For the first milestone, devise the missing event formats, explain generally how the implementation would work, any considerations, assumptions, and questions coming up during that process.

For the second milestone please keep as close to this description as possible. If you have ideas for improvements, a superior ruleset, or even believe there is a bug in the specification, you should definitely make a comment about it. If you would also like to put it in code, do it in a separate pull request.

For a better feedback experience, submit all code for these milestones as a single pull request.

We prefer single purpose packages, libraries and functions over frameworks, toolchains, boilerplate and classes. For tests we prefer https://www.npmjs.com/package/tape.

For an example of another service on the network, see https://github.com/paylike/beith.

For another example of code style (less important) and file layout, have a look at https://github.com/srcagency/symbolic-chain.

Read about pull-streams in this introduction and in their documentation.

Here's a contrived example of using the network:

const {pull, drain} = require('pull-stream')

function createServer({network}) {
  pull(
    network.createSource(),
    drain(event => {
      if (event.type !== 'ping') return
      network.respond(event, {type: 'pong'})
    })
  )

  return {close: () => {}}
}
@tjconcept
Copy link
Author

Note the https://github.com/paylike/beith repository is private. Write me at thomas@paylike.io to get access.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment