Benzinga Backend Challenge, A HTTP receiver and webhook forwarder

benzinga-backend-challenge

Benzinga Backend Challenge, a simple webhook receiver and forwarder.

The application should be a basic webhook receiver that has two endpoints.

  1. GET /healthz - should return HTTP 200-OK and “OK” as a string in the body
  2. POST /log - should accept JSON payload
{
    "user_id": 1,
    "total": 1.65,
    "title": "delectus aut autem",
    "meta": {
        "logins": [{
            "time": "2020-08-08T01:52:50Z",
            "ip": "0.0.0.0"
        }],
        "phone_numbers": {
            "home": "555-1212",
            "mobile": "123-5555"
        }
    },
    "completed": false
}

Requirements

  • The application should have three configurable values that should be read from environment variables:
    • batch size
    • batch interval
    • post endpoint
  • The application should deserialize the JSON payload received at /log endpoint into a struct.
  • Retain them all in-memory.
  • When batch size is reached OR the batch interval has passed forward the collected records as an array to the post endpoint.
  • Clear the in-memory cache of objects.
  • Logger ("github.com/sirupsen/logrus")
    • log an initialization message on startup
    • On each HTTP request
    • Each time it sends a batch
      • log the batch size.
      • result status code.
      • duration of the POST request to the external endpoint.

Addtional Requirements

  • If the POST fails
    • Retry 3 times, waiting 2 seconds before each retry.
    • After 3 failures log this failure and exit.
  • Testing for the Post endpoint output will be done against a service such as http://requestbin.net.

Arguments

  • Can be set through os env or overriding through flag args passed while running the build
  • Flags
batch-interval duration
        Batch Interval (default 10s)
  -batch-size int
        Batch Size (default 10)
  -http string
        HTTP  (default ":8080")
  -post-endpoint string
        Post Endpoint

OR

  • Env
WEBHOOK_POST_ENDPOINT=
   
    
WEBHOOK_BATCH_SIZE=
    
     
WEBHOOK_BATCH_INTERVAL=
     

     
    
   

Algorithm / Implementation

  • A buffered channel is init at program startup, if batch size > 0, buffered channel = 2*batch_size or 100 by default.
  • Buffered channel will make sure, /log is not blocked deserializing while the forwarder consumer is processing.
  • At same, time HTTP handlers / receivers are regsitered. (Routing is handled via gorrila/mux).
  • /log recieves the json, deserialize it in the defined struct and pushes to the buffered channel.
  • A forwarder consumer is started in the background and it iterates over buffer channel and starts pushing to unbuffered channel to be processed by another background consumer.
  • forwarder consumer itself regsiter a background process which starts a forever blocking select channel.
  • select channel has three cases, either a batch_size is full or batch_interval is reached or accumualte the msg in in-memory array.
  • When the batch(size/interval) limit is reached, it forwards the accumualted msgs to webhook endpoint as per the requirement.
  • if there is a error in the "post call" after three retries, it sends the error to err channel and the programs exits as per the requirement.

Scope of Improvements

  • Start forwarder consumer in waitgroup so it multiple consumers could be started in background in case of high throughput.
  • Add more unit tests 🙈

github-action

  • On every push to github, it runs linter / test and docker build
  • #TODO upload the docker build to GCR (but it requires a paid gcr account)

Build

  • make build puts the binary executable in $root/build folder.
  • it's good to run make lint test before the make build command to ensure lint and test passes.
  • make docker-build generates the docker image in $root/build folder.

Lint

  • make lint runs the golang-ci lint (installs it if not present) and runs the linter as defined in root/.golangci.yml.

Test

  • make test runs all the test in main package and generates the coverage report.

cmd

  • main http service is inside the cmd/benzinga-backend-challenge

Postman Code for easy accesibilty

  • Log Payload
curl -X POST \
  http://localhost:8080/log \
  -H 'cache-control: no-cache' \
  -H 'content-type: application/json' \
  -d '{
    "user_id": 1,
    "total": 1.65,
    "title": "delectus aut autem",
    "meta": {
        "logins": [{
            "time": "2020-08-08T01:52:50Z",
            "ip": "0.0.0.0"
        }],
        "phone_numbers": {
            "home": "555-1212",
            "mobile": "123-5555"
        }
    },
    "completed": false
}'
  • Health Check
curl -X GET \
  http://localhost:8080/healthz \
  -H 'cache-control: no-cache'
Similar Resources

Go (golang) http calls with retries and backoff

pester pester wraps Go's standard lib http client to provide several options to increase resiliency in your request. If you experience poor network co

Dec 28, 2022

Simple HTTP and REST client library for Go

Resty Simple HTTP and REST client library for Go (inspired by Ruby rest-client) Features section describes in detail about Resty capabilities Resty Co

Jan 1, 2023

A Go HTTP client library for creating and sending API requests

A Go HTTP client library for creating and sending API requests

Sling Sling is a Go HTTP client library for creating and sending API requests. Slings store HTTP Request properties to simplify sending requests and d

Jan 7, 2023

HTTP Load Testing And Benchmarking Tool

GBench HTTP Load Testing And Benchmarking Tool inspired by Apache Benchmark and Siege. Requirements You need Golang installed and ready on your system

Jan 2, 2020

HTTP/HTTPS load testing and benchmarking tool

Introduction I wrote that code because: (the obvious reason::I love to write code in Go) We are working so hard to optimize our servers - why shouldn'

Dec 5, 2022

Replacement of ApacheBench(ab), support for transactional requests, support for command line and package references to HTTP stress testing tool.

stress stress is an HTTP stress testing tool. Through this tool, you can do a stress test on the HTTP service and get detailed test results. It is ins

Aug 23, 2022

httpreq is an http request library written with Golang to make requests and handle responses easily.

httpreq is an http request library written with Golang to make requests and handle responses easily. Install go get github.com/binalyze/http

Feb 10, 2022

A golang tool which makes http requests and prints the address of the request along with the MD5 hash of the response.

Golang Tool This repository is a golang tool which makes http requests to the external server and prints the address of the request along with the MD5

Oct 17, 2021

Basic repository with HTTP ping api and db setup

Simple API Simple REST API with database (postgres) integration HighLevel Agenda Integrating with postgres (few concepts) Live code walkthrough Detail

Jan 27, 2022
Fast HTTP package for Go. Tuned for high performance. Zero memory allocations in hot paths. Up to 10x faster than net/http
Fast HTTP package for Go. Tuned for high performance. Zero memory allocations in hot paths. Up to 10x faster than net/http

fasthttp Fast HTTP implementation for Go. Currently fasthttp is successfully used by VertaMedia in a production serving up to 200K rps from more than

Jan 2, 2023
Speak HTTP like a local. (the simple, intuitive HTTP console, golang version)

http-gonsole This is the Go port of the http-console. Speak HTTP like a local Talking to an HTTP server with curl can be fun, but most of the time it'

Jul 14, 2021
Http client call for golang http api calls

httpclient-call-go This library is used to make http calls to different API services Install Package go get

Oct 7, 2022
fhttp is a fork of net/http that provides an array of features pertaining to the fingerprint of the golang http client.

fhttp The f stands for flex. fhttp is a fork of net/http that provides an array of features pertaining to the fingerprint of the golang http client. T

Jan 1, 2023
NATS HTTP Round Tripper - This is a Golang http.RoundTripper that uses NATS as a transport.

This is a Golang http.RoundTripper that uses NATS as a transport. Included is a http.RoundTripper for clients, a server that uses normal HTTP Handlers and any existing http handler mux and a Caddy Server transport.

Dec 6, 2022
Simple HTTP package that wraps net/http

Simple HTTP package that wraps net/http

Jan 17, 2022
Http-conection - A simple example of how to establish a HTTP connection using Golang

A simple example of how to establish a HTTP connection using Golang

Feb 1, 2022
Docker-Project - A simplified backend that listens to POST request

This is a simplified backend that listens to POST request. Once it receives such a request it will push it to a PostgreSQL database.

Feb 5, 2022
This is a simple single-host reverse proxy that intercept and save HTTP requests and responses
This is a simple single-host reverse proxy that intercept and save HTTP requests and responses

HTTP Telescope Debug HTTP requests using a reverse proxy. Description This is a simple single-host reverse proxy that intercept and save HTTP requests

Mar 20, 2022
Goget will send a http request, and show the request time, status, response, and save response to a file

Goget will send a http request, and show the request time, status, response, and save response to a file

Feb 9, 2022