Code solution for question against internship application at Eluvio

Overview

Eluvio Problem Statement

Imagine you have a program that needs to look up information about items using their item ID, often in large batches.

Unfortunately, the only API available for returning this data takes one item at a time, which means you will have to perform one query per item. Additionally, the API is limited to five simultaneous requests. Any additional requests will be served with HTTP 429 (too many requests).

Write a client utility for your program to use that will retrieve the information for all given IDs as quickly as possible without triggering the simultaneous requests limit, and without performing unnecessary queries for item IDs that have already been seen.

API Usage:

GET https://challenges.qluv.io/items/:id

Required headers:

Authorization: Base64(:id) Example:

curl https://challenges.qluv.io/items/cRF2dvDZQsmu37WGgK6MTcL7XjH -H "Authorization: Y1JGMmR2RFpRc211MzdXR2dLNk1UY0w3WGpI"

My Solution in Go

My idea is to create 5 GoRoutines that will independently scheduling the HTTP requests one by one from the same queue. I have used a channel with 5 buffer size for implementing this queue and each of these GoRoutines will keep popping off a user ID and sending the HTTP GET request for it.

GET request

Here is the function that will be invoked by each of the GoRoutine to send an individual HTTP GET request.

func sendRequest(baseUrl string, itemID string) []interface{} {...}

It takes as input the base URL and the item ID (it will concatenate the item ID to the base string to form the final URL). It first generates the Authorization header using the item ID (by converting to base64 as mentioned in the problem statement). And then it sends the GET request to the final URL with this auth header, and captures the response body and status code inside an interface structure that it returns back to the caller.

GoRoutine

Here is the function whose 5 concurrent instances will be running and this will keep invoking the sendRequest() function to send the GET requests and use the response status code to either print out the returned item info if success, or start a (concurrent) backoff mechanism where the item will be re-queried after certain duration and will be dropped after certain number of max attempts.

func requestInfo(baseUrl string, channel chan []interface{}) {...}

It takes as input the base URL and the channel on which it keeps monitoring for any available jobs (itemIDs) to perform on (send the query req). It will further invoke another concurrent goroutine for backoff process if a query is not responded with a success code. If the maximum number of attempts is reached for a particular itemID, it will drop it and mark it as 'not visited' in a dictionary - which can later be used by the main function to re-consider this same userID (if it comes again).

Backoff Handler

Here is the function that performs the backoff functionality. It's invoked by the GoRoutine requestInfo() if a particular itemID's query is not successful.

func backoffHandler(item string, attempt int, channel chan []interface{}) {...}

It takes as input the itemID (so that it can re-queue it to the channel), the attempt count (it will increment this before re-queueing) and the channel on which it will requeue the itemID. It also runs the backoff timer according to the attempt count. Note that this runs as another (sub) GoRoutine since other items scheduling shouldn't be held on waiting for this to be re-queued.

Main

The main function will invoke the 5 main GoRoutines (requestInfo()) as shown below:

for idx := 0; idx < 5; idx++ {
    go requestInfo(baseUrl, channel)
}

A channel with size 5 is also created along with this which will be used for continuous queueing of jobs (itemIDs to be queried):

channel := make(chan []interface{}, 5)

It's assumed that the itemID's are all listed in the string array itemList. Then each itemID's are sent to the channel using a for loop to be queried by the GoRoutines:

for current := 0; current < len(itemList); current++ {...}

A dictionary is maintained globally to ensure that the same itemID that's already been queried is not re-queried:

var dict map[string]bool = make(map[string]bool)

It will be written by the main function once to mark the itemID while sending it to the channel first, and also used by the GoRoutine to mark an itemID in case of failure of query. Hence a mutex is used to use this dictionary at both the places.

Finally, a Waitgroup is used to ensure that all the queries are finished completely (either successfully or failed after all the backoffs) before we close the channel and end the main function. It's 'added' once at each addition of itemID from the itemList, and is marked 'Done' only when it's either successully or failed completely.

You might also like...
Simple boilerplate code to get started with building and deploying a serverless CRUD API

Simple boilerplate code to get started with building and deploying a serverless CRUD API with Go, MongoDB and Netlify

Test-Driven Development code kata in Golang

Bowling Kata Golang Test-Driven Development code kata in Golang Bowling Rules The game consists of 10 frames. In each frame the player has two rolls t

A series of small code snipppets & exercises to learn Go.

Learning-Go A series of small code snipppets & exercises to learn Go. WARNING: During this excercise you will be learning along with me, I am not your

An open source, online coding platform that offers code practice and tutoring in 50 different programming languages
An open source, online coding platform that offers code practice and tutoring in 50 different programming languages

Exercism Golang En este repositorio voy a subir los ejercicios de la plataforma

Source code of the 100 Go Mistakes book

100 Go Mistakes and How to Avoid Them Source code of 100 Go Mistakes and How to Avoid Them. Table of Contents Chapter 1 - Introduction Chapter 2 - Cod

VHDL Simulator, code VHDL in your browser! 🤖
VHDL Simulator, code VHDL in your browser! 🤖

VHDL Runner 🤖 VHDL Simulator, code VHDL in your browser! 🤖 Usage Go to https://vhdl.mateuszwozniak.com/ Next, type some VHDL code, with appropriate

Mastering-go-exercises - Some code examples from Mihalis Tsoukalos book titled Mastering GO

Mastering go exercises This is a training repository. Here are some code example

A source code analyzer built for surfacing features of interest and other characteristics to answer the question 'What's in the code?' quickly using static analysis with a json based rules engine. Ideal for scanning components before use or detecting feature level changes.
A programming job interview question problem

Unscramble a scrambled URL Problem statement The problem statement follows. I copied it literally because there's no good way to summarize and retain

Simple project by Follow up Question from LINE MAN Wongnai about summary covid stats from API.

Simple JSON API to summarize COVID-19 stats API created by Follow-up Question from LINE MAN Wongnai. they can show summary covid stats from Province a

A Telegram bot that asks you a question and evaluate the response you provide.
A Telegram bot that asks you a question and evaluate the response you provide.

PiSquared A Telegram bot that asks you a question and evaluate the response you provide. Thanks to the labse_bert model, the evaluation of the answer

Golang Clean Architecture based on Uncle Bob's Clean Architecture and Summer internship in 2021

clean-architecture-api Description This is an example of implemention of Clean Architecture in Golang projects. This project has 4 layer : Infrastruct

internship selection task for 3rd year VIT Bhopal in Appointy

Appointy_tech_task1 internship selection task for 3rd year VIT Bhopal in Appointy To run : Requirements : To be able to show the desired features of c

My Simple Instagram-Clone API task submission, conducted by Appointy for internship shortlisting.

go-pointy Go-Pointy is a simple Instagram API Clone, made using GoLang. I had tried my best to not be lazy and finish the tasks, as a beginner to the

Appointy internship task
Appointy internship task

appointy_task_Krishna_Harchandani Appointy internship task Appointy_Krishna_Harchandani Appointy Internship Task Instagram Backend API Krishna Harchan

Chaostheory task1 - This is repository for Chaos Theory Internship Program

Chaos Theory Internship - Take Home Task. Hyeonwoo KIM(clo3olb) City Universiry

Exploitation of CVE-2018-18925 a Remote Code Execution against the Git self hosted tool: Gogs.
Exploitation of CVE-2018-18925 a Remote Code Execution against the Git self hosted tool: Gogs.

CVE-2018-18925 Exploitation of CVE-2018-18925 a Remote Code Execution against the Git self hosted tool: Gogs. Gogs is based on the Macaron framework.

Hotswap provides a solution for reloading your go code without restarting your server, interrupting or blocking any ongoing procedure.
Hotswap provides a solution for reloading your go code without restarting your server, interrupting or blocking any ongoing procedure.

Hotswap provides a solution for reloading your go code without restarting your server, interrupting or blocking any ongoing procedure. Hotswap is built upon the plugin mechanism.

Owner
Kunal Kishore
Kunal Kishore
Golang Clean Architecture based on Uncle Bob's Clean Architecture and Summer internship in 2021

clean-architecture-api Description This is an example of implemention of Clean Architecture in Golang projects. This project has 4 layer : Infrastruct

daiki sakuma 4 Feb 20, 2022
My solution for a Go exercises series called gophercises - exercise #1

My solution for a Go exercises series called gophercises - exercise #1

null 0 Jan 11, 2022
Example repository for embedding Litestream in a Go application.

Litestream as Library This repository is an example of embedding Litestream as a library in a Go application. The Litestream API is not stable so you

Ben Johnson 40 Dec 6, 2022
Boilerplate for writing Go applications without framework using hexagonal application development approach

Boilerplate for writing Go applications without framework using hexagonal application development approach

Marko Kovačević 28 Dec 2, 2022
Repository for COMP 429 Programming Assignment# 1 - A simple chat application, by Sabra Bilodeau.

Chatty COMP 429 Programming Assignment 1 A Chat Application for Remote Message Exchange by Sabra Bilodeau Getting Started with Chatty Building the Pro

Sabra Bilodeau 0 Nov 28, 2021
Markdown version of Reverse Engineering the source code of the BioNTech/Pfizer SARS-CoV-2 Vaccine

The big BNT162b2 archive All vaccine data here is sourced from this World Health Organization document. This describes the RNA contents of the BNT162b

null 163 Dec 2, 2022
Assert your Go code is inlined and bounds-check eliminated

gcassert gcassert is a program for making assertions about compiler decisions in Golang programs, via inline comment directives like //gcassert:inline

Jordan Lewis 178 Oct 27, 2022
Go-Notebook is inspired by Jupyter Project (link) in order to document Golang code.

Go-Notebook Go-Notebook is an app that was developed using go-echo-live-view framework, developed also by us. GitHub repository is here. For this proj

Arturo Elias 33 Jan 9, 2023
Example code for my Cadence Intro Workshop

Temporal Intro Workshop This repository contains example code for my Temporal Intro Workshop. Prerequisites Git, Make, etc. Make sure you have the lat

Márk Sági-Kazár 21 Dec 18, 2022
Sample code for my Go Deadlocks talk

Go Deadlocks Talk This is sample code for my Go Deadlocks talk. Simple simple - a super simple deadlock simple2 - the same but with an extra Go deadlo

Nick Craig-Wood 9 Jul 30, 2022