The flexqueue package provides some hybrid data structures which are intended to cover the most common use cases for highly performant single lane message queues and ordered lists. No single use case is likely to use all of the provided features or methods, but integral to the design is that no arbitrary limitations were imposed.
No external dependencies, this package only uses internal go libraries.
Care was taken to implement all methods with a constant 0(1) time signature. This means that performance will be effected linearly as the collection size grows, no exponential degradation.
Care was taken to be as non-intrusive and non-prescriptive as possible. These data structures therefore do not spawn additional go routines or dictate any item interface. All features are optional and no major performance penalty is incurred by opting out of a feature.
Because these are hybrid data structures which blend several different concepts, I've maintained a coherent and consistent naming convention across everything. Depending on your existing bias of naming conventions, you may be required to adapt the language you are used to.
FlexList is a high performance ordered map. Internally it uses a combination of a double linked list via container/list for item order and a map of strings for an index.
FlexQueue is a combined FIFO/LIFO single lane queue. FlexQueue is essentially a wrapper for FlexList but provides the following additional queue concepts:
- Thread safety via mutex
- Max queue length
- Message de-duplication
- Message TTL/expiration with callback
- For a FIFO (first-in first-out) queue use
PushBackfor insertions andPullFrontfor extractions. - For a LIFO (last-in first-out) queue use
PushFrontfor insertions andPullFrontfor extractions. - To leave a message in a FIFO queue while it is being processed use
ReadFrontandRemoverather thanPullFront.
- To utilize message de-duplication provide a
digestvalue based on a hash of message contents. You implement the digest algorithm. - To avoid message de-duplication provide a unique
digestvalue for every message.
- TTL is optional, and the configuration is handled on each message insertion with a
time.Durationand a callback function. - A queue may contain a mix of messages with and without a TTL.
- TTL uses
time.Durationto guarantee the expiration accuracy regardless of server time zone settings. - If you messages use expiration dates then you should map them to a
time.Durationat the time of insertion. - All read/write functions which access a message in the queue will transparently perform a TTL analysis and if the message is expired it will be automatically removed from the queue and the access method will behave as if the message had not existed. The only exceptions to this are the
Len,EmptyandFullmethods which do not perform TTL analysis and can therefore count expired messages. We did this to keep these counting methods performant. If you want to take the performance hit for better accuracy then callPrunefirst.