cubq v0.2.0 CubQ View Source

CubQ is a queue abstraction on top of CubDB. It implements persistent local (double-ended) queue and stack semantics.

Usage

CubQ is given a CubDB process and a queue identifier upon start:

{:ok, db} = CubDB.start_link(data_dir: "my/data/directory")
{:ok, pid} = CubQ.start_link(db: db, queue: :my_queue_id)

Queues

Queue semantics are implemented by the enqueue/2 and dequeue/1 functions:

CubQ.enqueue(pid, :one)
#=> :ok

CubQ.enqueue(pid, :two)
#=> :ok

CubQ.dequeue(pid)
#=> {:ok, :one}

CubQ.dequeue(pid)
#=> {:ok, :two}

# When there are no more elements in the queue, [`dequeue/1`](#dequeue/1) returns `nil`:

CubQ.dequeue(pid)
#=> nil

Note that elements can be any Elixir (or Erlang) term:

CubQ.enqueue(pid, %SomeStruct{foo: "bar"})
#=> :ok

CubQ.dequeue(pid)
#=> {:ok, %SomeStruct{foo: "bar"}}

The queue is actually double-ended, so elements can be prepended too:

CubQ.enqueue(pid, :one)
#=> :ok

CubQ.prepend(pid, :zero)
#=> :ok

CubQ.dequeue(pid)
#=> {:ok, :zero}

Stacks

Stack semantics are implemented by the push/2 and pop/1 functions:

CubQ.push(pid, :one)
#=> :ok

CubQ.push(pid, :two)
#=> :ok

CubQ.pop(pid)
#=> {:ok, :two}

CubQ.pop(pid)
#=> {:ok, :one}

# When there are no more elements in the stack, [`pop/1`](#pop/1) returns `nil`:

CubQ.pop(pid)
#=> nil

Mixing things up

As the underlying data structure used for stacks and queues is the same, queue and stack semantics can be mixed on the same queue.

Link to this section Summary

Functions

Returns a specification to start this module under a supervisor.

Deletes all elements from the queue.

Removes an element from the beginning of the queue and returns it.

Inserts an element at the end of the queue.

Returns the element at the beginning of the queue without removing it.

Returns the element at the end of the queue without removing it.

Removes an element from the end of the queue and returns it.

Inserts an element at the beginning of the queue.

Starts a CubQ process without link.

Starts a CubQ process linked to the calling process.

Link to this section Types

Link to this type

element()

View Source
element() :: term()
Link to this type

option()

View Source
option() :: {:db, GenServer.server()} | {:queue, term()}

Link to this section Functions

Link to this function

append(pid, element)

View Source
append(GenServer.server(), element()) :: :ok | {:error, term()}

Same as enqueue/2

Returns a specification to start this module under a supervisor.

See Supervisor.

Link to this function

delete_all(pid, batch_size \\ 100)

View Source
delete_all(GenServer.server(), pos_integer()) :: :ok | {:error, term()}

Deletes all elements from the queue.

The elements are deleted in batches, and the size of the batch can be specified as the optional second argument.

Link to this function

dequeue(pid)

View Source
dequeue(GenServer.server()) :: {:ok, element()} | nil | {:error, term()}

Removes an element from the beginning of the queue and returns it.

It returns {:ok, element} if there are elements in the queue, nil if the queue is empty, and {:error, cause} on error.

Example:

CubQ.enqueue(pid, :one)
#=> :ok

CubQ.enqueue(pid, :two)
#=> :ok

CubQ.dequeue(pid)
#=> {:ok, :one}

CubQ.dequeue(pid)
#=> {:ok, :two}
Link to this function

enqueue(pid, element)

View Source
enqueue(GenServer.server(), element()) :: :ok | {:error, term()}

Inserts an element at the end of the queue.

The element can be any Elixir (or Erlang) term.

Example:

CubQ.enqueue(pid, :one)
#=> :ok

CubQ.enqueue(pid, :two)
#=> :ok

CubQ.dequeue(pid)
#=> {:ok, :one}
Link to this function

peek_first(pid)

View Source
peek_first(GenServer.server()) :: {:ok, element()} | nil | {:error, term()}

Returns the element at the beginning of the queue without removing it.

It returns {:ok, element} if there are elements in the queue, nil if the queue is empty, and {:error, cause} on error.

Example:

CubQ.enqueue(pid, :one)
#=> :ok

CubQ.enqueue(pid, :two)
#=> :ok

CubQ.peek_first(pid)
#=> {:ok, :one}

CubQ.dequeue(pid)
#=> {:ok, :one}
Link to this function

peek_last(pid)

View Source
peek_last(GenServer.server()) :: {:ok, element()} | nil | {:error, term()}

Returns the element at the end of the queue without removing it.

It returns {:ok, element} if there are elements in the queue, nil if the queue is empty, and {:error, cause} on error.

Example:

CubQ.enqueue(pid, :one)
#=> :ok

CubQ.enqueue(pid, :two)
#=> :ok

CubQ.peek_last(pid)
#=> {:ok, :two}

CubQ.pop(pid)
#=> {:ok, :two}
Link to this function

pop(pid)

View Source
pop(GenServer.server()) :: {:ok, element()} | nil | {:error, term()}

Removes an element from the end of the queue and returns it.

It returns {:ok, element} if there are elements in the queue, nil if the queue is empty, and {:error, cause} on error.

Example:

CubQ.push(pid, :one)
#=> :ok

CubQ.push(pid, :two)
#=> :ok

CubQ.pop(pid)
#=> {:ok, :two}

CubQ.pop(pid)
#=> {:ok, :one}
Link to this function

prepend(pid, element)

View Source
prepend(GenServer.server(), element()) :: :ok | {:error, term()}

Inserts an element at the beginning of the queue.

The element can be any Elixir (or Erlang) term.

Example:

CubQ.enqueue(pid, :one)
#=> :ok

CubQ.prepend(pid, :zero)
#=> :ok

CubQ.dequeue(pid)
#=> {:ok, :zero}

CubQ.dequeue(pid)
#=> {:ok, :one}
Link to this function

push(pid, element)

View Source
push(GenServer.server(), element()) :: :ok | {:error, term()}

Same as enqueue/2.

Normally used together with pop/1 for stack semantics.

Starts a CubQ process without link.

The argument is a keyword list of options, see start_link/1 for details.

Starts a CubQ process linked to the calling process.

The argument is a keyword list of options:

  • db (required): the pid (or name) of the CubDB process for storing the queue

  • queue (required): the identifier of the queue. It can be any Elixir term, but typically one would use an atom, like :my_queue

GenServer options like name and timeout can also be given, and are forwarded to GenServer.start_link/3 as the third argument.