• Stars
    star
    207
  • Rank 189,769 (Top 4 %)
  • Language
    Go
  • License
    MIT License
  • Created almost 4 years ago
  • Updated almost 2 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A simple, single binary, message queue. Supports HTTP/2 and Redis Protocol.

miniqueue

Tests Go Report Card GitHub release (latest by date)

A stupid simple, single binary message queue using HTTP/2 or Redis Protocol.

Most messaging workloads don't require enormous amounts of data, endless features or infinite scaling. Instead, they'd probably be better off with something dead simple.

miniqueue is just that. A ridiculously simple, high performance queue. You can publish bytes to topics and be sure that your consumers will receive what you published, nothing more.

Features

  • Redis Protocol Support
  • Simple to run
  • Very fast, see benchmarks
  • Not infinitely scalable
  • Multiple topics
  • HTTP/2
  • Publish
  • Subscribe
  • Acknowledgements
  • Persistence
  • Prometheus metrics [WIP]

API

Redis

You can communicate with miniqueue using any major Redis library which supports custom commands. The command set is identical to the HTTP/2 implementation and listed under the commands heading.

Examples of using the Redis interface can be found in the redis_test.go file.

HTTP/2

  • POST /publish/:topic, where the body contains the bytes to publish to the topic.

    curl -X POST https://localhost:8080/publish/foo --data "helloworld"
  • POST /subscribe/:topic - streams messages separated by \n

    • client → server: "INIT"
    • server → client: { "msg": [base64], "error": "...", dackCount: 1 }
    • client → server: "ACK"
  • DELETE /:topic - deletes the given topic, removing all messages. Note, this is an expensive operation for large topics.

You can also find examples in the ./examples/ directory.

Usage

miniqueue runs as a single binary, persisting the messages to the filesystem in a directory specified by the -db flag and exposes an HTTP/2 server on the port specified by the -port flag.

Note: As the server uses HTTP/2, TLS is required. For testing, you can generate a certificate using mkcert and replace the ones in ./testdata as these will not be trusted by your client, or specify your own certificate using the -cert and -key flags.

Usage of ./miniqueue:
  -cert string
        path to TLS certificate (default "./testdata/localhost.pem")
  -db string
        path to the db file (default "./miniqueue")
  -human
        human readable logging output
  -key string
        path to TLS key (default "./testdata/localhost-key.pem")
  -level string
        (disabled|debug|info) (default "debug")
  -period duration
        period between runs to check and restore delayed messages (default 1s)
  -port int
        port used to run the server (default 8080)

Once running, miniqueue will expose an HTTP/2 server capable of bidirectional streaming between client and server. Subscribers will be delivered incoming messages and can send commands ACK, NACK, BACK etc. Upon a subscriber disconnecting, any outstanding messages are automatically NACK'ed and returned to the front of the queue.

Messages sent to subscribers are JSON encoded, containing additional information in some cases to enable certain features. The consumer payload looks like:

{
  "msg": "dGVzdA==", // base64 encoded msg
  "dackCount": 2,    // number of times the msg has been DACK'ed
}

In case of an error, the payload will be:

{
  "error": "uh oh, something went wrong"
}

To get you started, here are some common ways to get up and running with miniqueue.

Start miniqueue with human readable logs
λ ./miniqueue -human
Start miniqueue with custom TLS certificate
λ ./miniqueue -cert ./localhost.pem -key ./localhost-key.pem
Start miniqueue on custom port
λ ./miniqueue -port 8081

Docker

As of v0.7.0 there are published miniqueue docker images available in the Docker hub repository tomarrell/miniqueue.

It is recommended to use a tagged release build. The tag latest tracks the master branch.

With the TLS certificate and key in a relative directory ./certs (can be generated using mkcert).

./certs
├── localhost-key.pem
└── localhost.pem

You can execute the following Docker command to run the image.

$ docker run \
  -v $(pwd)/certs:/etc/miniqueue/certs \
  -p 8080:8080 \
  tomarrell/miniqueue:v0.7.0 \
  -cert /etc/miniqueue/certs/localhost.pem \
  -key /etc/miniqueue/certs/localhost-key.pem \
  -db /var/lib/miniqueue \
  -human

Examples

To take a look at some common usage, we have compiled some examples for reference in the ./examples/ directory. Here you will find common patterns such as:

Commands

A client may send commands to the server over a duplex connection. Commands are in the form of a JSON string to allow for simple encoding/decoding.

Available commands are:

  • "INIT": Establishes a new consumer on the topic. If you are consuming for the first time, this should be sent along with the request.

  • "ACK": Acknowledges the current message, popping it from the topic and removing it.

  • "NACK": Negatively acknowledges the current message, causing it to be returned to the front of the queue. If there is a ready consumer waiting for a message, it will immediately be delivered to this consumer. Otherwise it will be delivered as as one becomes available.

  • "BACK": Negatively acknowledges the current message, causing it to be returned to the back of the queue. This will cause it to be processed again after the currently waiting messages.

  • "DACK [seconds]": Negatively acknowledges the current message, placing it on a delay for a certain number of seconds. Once the delay expires, on the next tick given by the -period flag, the message will be returned to the front of the queue to be processed as soon as possible.

    DACK'ed messages will contain a dackCount key when consumed. This allows for doing exponential backoff for the same message if multiple failures occur.

Benchmarks

As miniqueue is still under development, take these benchmarks with a grain of salt. However, for those curious:

Publish

λ go-wrk -c 12 -d 10 -M POST -body "helloworld" https://localhost:8080/publish/test
Running 10s test @ https://localhost:8080/publish/test
  12 goroutine(s) running concurrently
142665 requests in 9.919498387s, 7.89MB read
Requests/sec:           14382.28
Transfer/sec:           814.62KB
Avg Req Time:           834.36µs
Fastest Request:        190µs
Slowest Request:        141.091118ms
Number of Errors:       0

Consume + Ack

λ ./bench_consume -duration=10s
consumed 42982 times in 10s
4298 (consume+ack)/second

Running on my MacBook Pro (15-inch, 2019), with a 2.6 GHz 6-Core Intel Core i7 using Go v1.15.

Contributing

Contributors are more than welcome. Please feel free to open a PR to improve anything you don't like, or would like to add. No PR is too small!

License

This project is licensed under the MIT license.

More Repositories

1

lbadd

LBADD: An experimental, distributed SQL database
Go
387
star
2

wrapcheck

A Go linter to check that errors from external packages are wrapped
Go
299
star
3

rust-elias-fano

Elias-Fano encoding implementation in Rust
Rust
28
star
4

vim-npr

Sensible 'gf' for Node Path Relative JS module resolution per project 🐿
Vim Script
23
star
5

rasp-ws2812b

Controlling WS2812b LED's using Rust on the Raspberry Pi
Rust
17
star
6

snake

Parallel, abstract Snake engine 🐍
Go
9
star
7

poker_tracker_api

A Poker tracking API written in Go
Go
7
star
8

talks

Slides and notes for talks that I've given
Go
7
star
9

generative

Generative art experiments
Go
7
star
10

poker_tracker_ui

React UI for Poker Tracker App
JavaScript
6
star
11

R2D2

React HOC for ensuring data from store, otherwise dispatching for it
JavaScript
5
star
12

ChangeCMS

Change - A lightweight NodeJS CMS platform built with Meteor
CSS
5
star
13

rmraf

Play with fire, and your root directory's existence!
JavaScript
5
star
14

tools

Personal tooling configuration
Vim Script
4
star
15

gif_emoji

Turn images into animated rotating gifs
Python
4
star
16

tomarrellcom

Old personal site source. Includes interactive snake game written in vanilla JS working on both desktop and mobile.
CSS
4
star
17

React-Express-Skeleton

A Simple React + Express Application Skeleton
JavaScript
4
star
18

website

Personal website, ab 2019
JavaScript
3
star
19

blog

Personal blog, barely coherent
Go
3
star
20

sumup-lessons

Repo containing information for the Go programming lessons run at SumUp
Go
3
star
21

react-media-rtc

A lightweight WebRTC library for React apps
JavaScript
2
star
22

Date-Cake

A natural-language date calculator
JavaScript
2
star
23

tre

A simple, fast and interactive alternative to 'tree'
Rust
2
star
24

tomarrell

Add README.md to my GitHub profile
1
star
25

vim8

Vim8 specific dotfiles
Vim Script
1
star
26

rust-hands-on

Repo containing code used at the Rust functional programming hands-on meetup
Rust
1
star
27

SkiSim

A ski-field simulation with GUI written in Java including fully implemented multi-threading.
Java
1
star
28

MeteorTodo

Meteor Todo Application
JavaScript
1
star
29

tomarrell.co

My personal website and development blog.
CSS
1
star
30

BankErrorChecking

Project for Thales NZ. Checks for errors/inconsistencies in reports sent and received from a bank.
Python
1
star
31

dotfiles

Emacs configuration. Forked from @d4ncer
Emacs Lisp
1
star
32

cms-experiment

CSS
1
star
33

redcli

A simple Redis client for Pub/Sub
Go
1
star
34

multitouch

Go
1
star
35

plantower

A library for decoding data from the Plantower series of sensors
Go
1
star
36

o_f

Go
1
star
37

dots

Personally written & maintained custom dotfiles
Emacs Lisp
1
star
38

poker-v2

Poker Tracker reborn, in Rust
Rust
1
star
39

rust-cli-table

A CLI tabling tool which parses CSVs - Rust
Rust
1
star
40

Email-Scraper

Python
1
star
41

infra

Personal infrastructure manifests
Shell
1
star
42

emu

A tool to help manage .env files per project
Rust
1
star
43

photos

Documenting my personal photo backup strategy
1
star