View Source PropertyTable (property_table v0.2.5)

In-memory key-value store with subscriptions

PropertyTable makes it easy to set up a key-value store where users can subscribe to changes based on patterns. PropertyTable refers to keys as properties. Properties have values and are timestamped as to when they received that value. Subscriptions make this library feel similar to Publish-Subscribe. Events, though, are only for changes to properties.

PropertyTable is useful when you want to expose a decent amount of state and let consumers pick and choose what parts interest them.

PropertyTable consumers express their interest in properties using "patterns". A pattern could be as simple as the property of interest or it could contain wildcards. This allows one to create hierarchical key-value stores, map-based stores, or just simple key-value stores with notifications.

PropertyTable is optionally persistent to disk. Keys and values are backed by ETS.

Summary

Types

PropertyTable configuration options

A match pattern

A property

A property/value tuple

A table_id identifies a group of properties

A properties value

Functions

Returns a specification to start a property_table under a supervisor. See Supervisor.

Delete the specified property

Delete all properties that match a pattern

Fetch a property with the time that it was set

Write any changes to disk

Get the current value of a property

Get all properties

Return available snapshot IDs

Get a list of all properties matching the specified property pattern

Update a property and notify listeners

Update many properties

Restart a previously saved snapshot

Take a snapshot of the property table

Start a PropertyTable's supervision tree

Subscribe to receive events

Stop subscribing to a property

Types

@type options() :: [
  name: table_id(),
  properties: [property_value()],
  tuple_events: boolean(),
  matcher: module(),
  persist_data_path: String.t(),
  persist_interval: pos_integer(),
  persist_max_snapshots: pos_integer(),
  persist_compression: 0..9
]

PropertyTable configuration options

See start_link/1 for usage.

@type pattern() :: any()

A match pattern

Just like properties, these can be anything but they have to be compatible with the PropertyTable.Matcher implementation.

The default is that patterns are string lists with the addition of wildcards like :_.

@type property() :: any()

A property

Properties can be anything, but in order to be useful, they need to be compatible with the PropertyTable.Matcher implementation.

In is common for this to be a string list ([String.t()]) since the default PropertyTable.Matcher works with those.

@type property_value() :: {property(), value()}

A property/value tuple

@type table_id() :: atom()

A table_id identifies a group of properties

@type value() :: any()

A properties value

These can be whatever makes sense to the PropertyTable user. The only constraint is that if you're using PropertyTable's persistence feature, it needs to be possible to save and restore them. This means that pids and references, for example, can't be used.

Functions

@spec child_spec(options()) :: Supervisor.child_spec()

Returns a specification to start a property_table under a supervisor. See Supervisor.

@spec delete(table_id(), property()) :: :ok

Delete the specified property

Link to this function

delete_matches(table, pattern)

View Source
@spec delete_matches(table_id(), pattern()) :: :ok

Delete all properties that match a pattern

Link to this function

fetch_with_timestamp(table, property)

View Source
@spec fetch_with_timestamp(table_id(), property()) ::
  {:ok, value(), integer()} | :error

Fetch a property with the time that it was set

Timestamps come from System.monotonic_time()

@spec flush_to_disk(table_id()) :: :ok | {:error, any()}

Write any changes to disk

If persistence is enabled for this property table, save the current state to disk immediately. The table is already written every :persist_interval, but this is avoid waiting after important changes.

Link to this function

get(table, property, default \\ nil)

View Source
@spec get(table_id(), property(), value()) :: value()

Get the current value of a property

@spec get_all(table_id()) :: [{property(), value()}]

Get all properties

This function might return a really long list so it's mainly intended for debug or convenience when you know that the table only contains a few properties.

@spec get_snapshots(table_id()) :: [{String.t(), String.t()}]

Return available snapshot IDs

This scans the snapshots directory and returns a list of tuples containing snapshot IDs and their full name.

@spec match(table_id(), pattern()) :: [{property(), value()}]

Get a list of all properties matching the specified property pattern

Link to this function

put(table, property, value)

View Source
@spec put(table_id(), property(), value()) :: :ok

Update a property and notify listeners

Link to this function

put_many(table, properties)

View Source
@spec put_many(table_id(), [{property(), value()}]) :: :ok

Update many properties

This is similar to calling put/3 several times in a row, but atomically. It is also slightly more efficient when updating more than one property.

Link to this function

restore_snapshot(table, snapshot_name)

View Source
@spec restore_snapshot(table_id(), String.t()) :: :ok | :noop

Restart a previously saved snapshot

If persistence is enabled for this property table, restore the current state of the PropertyTable to that of a past named snapshot

@spec snapshot(table_id()) :: {:ok, String.t()} | :noop

Take a snapshot of the property table

If persistence is enabled for this property table, save the current state and copy a snapshot of it into the /snapshots sub-directory of the set data directory.

This returns an ID for the snapshot that can be passed restore_snapshot/2.

@spec start_link(options()) :: Supervisor.on_start()

Start a PropertyTable's supervision tree

To create a PropertyTable for your application or library, add the following child_spec to one of your supervision trees:

{PropertyTable, name: MyTableName}

The :name option is required. All calls to PropertyTable will need to know it and the process will be registered under than name so be sure it's unique.

Options for properties and events:

  • :properties - a list of {property, value} tuples to initially populate the PropertyTable
  • :matcher - set the format for how properties and how they should be matched for triggering events. See PropertyTable.Matcher.
  • :tuple_events - set to true for change events to be in the old tuple format. This is not recommended for new code and hopefully will be removed in the future.

Options for persisting properties:

  • :persist_data_path - set to a directory where PropertyTable will persist the contents of the table to disk, snapshots will also be stored here.
  • :persist_interval - if set PropertyTable will persist the contents of tables to disk in intervals of the provided value (in milliseconds) automatically.
  • :persist_max_snapshots - Maximum number of manual snapshots to keep on disk before they are replaced - (oldest snapshots are replaced first.) Defaults to 25.
  • :persist_compression - 0..9 range to compress the terms when written to disk, see :erlang.term_to_binary/2. Defaults to 6.

Important

Setting :persist_data_path enables persistence. On initialization, if PropertyTable is able to load a snapshot, the data in the snapshot is used instead of the :properties option.

Link to this function

subscribe(table, pattern)

View Source
@spec subscribe(table_id(), pattern()) :: :ok

Subscribe to receive events

Link to this function

unsubscribe(table, pattern)

View Source
@spec unsubscribe(table_id(), pattern()) :: :ok

Stop subscribing to a property