Goroutine Admission Control

(Seb Pouplin) #1


I’m new to Go and currently writing a web service (using gingonic framework) that handles Vulnerability scans for network devices. This is the basic flow I intend to develop:

  • POST sent to /api/v1/devicescan with payload {“device”: “ROUTER1”}
  • Goroutine is created to launch a scan job and reports the scan result when finished

What I would like to achieve is to prevent API consumers from sending scans requests for a device that is already being scanned.

I’m thinking of 3 different potential solutions but would like some hints on which one would the most optimal:

  1. Assign the devices being scanned in channel and before launching a scan job, read channel values. If the device requested to be scanned is read from channel, then abort the operation. I understand that reading from a channel is a blocking operation but using select with default clause allows non-blocking channel operations. https://gobyexample.com/non-blocking-channel-operations.

  2. Use Postgres with a Temporary Table to hold current devices being scanned. Before launching a scan job, read the Temporary table rows to find out if the requested device is already being scanned. This would involve the overhead of having to launch DB queries before each scan job which may not be the best.

  3. Using gingonic API to list the ongoing requests and their values. I haven’t found out yet whether gingonic has an API for this.

Thanks in advance.

(Johan Dahl) #2
  1. How long will a scan take, milliseconds, seconds, minutes
  2. If a second request comes in. Should it also wait for the scan to complete and get the result or should it get som error message?

(George Calianu) #3

You can use an array or a map of structs with informations about devices curently scaned and a semaphore for every device. You will start a new scan only if the semaphore is clear, device is not in the list or whatever. Also you can approach with channels but i think that database tables is a little overkill.

(Seb Pouplin) #4

Thanks for the reply.

A device scan usually takes ~10 seconds depending on network latency. If the second scan request for the same device comes in, then an error message should be returned to inform that the device is currently being scanned.

(Seb Pouplin) #5

Thanks for the suggestions. I now think using a simple FIFO queue with slice would probably do the job.

(Onezino Moreira) #6

You could use a map do avoid more than one run.

func longWork( params... ) {
  delete(jobs, id)


if _ ,ok = jobs[id]; ok {
    //already run

jobs[id] = true
queue <- id