All Projects → sheharyarn → Memento

sheharyarn / Memento

Licence: mit
Simple + Powerful interface to the Mnesia Distributed Database 💾

Programming Languages

elixir
2628 projects
erlang
1774 projects

Projects that are alternatives of or similar to Memento

Zookeeper
Apache ZooKeeper
Stars: ✭ 10,061 (+1585.26%)
Mutual labels:  hacktoberfest, database, distributed-systems
Oblecto
Oblecto is a media server, which streams media you already own, and is designed to be at the heart of your entertainment experience. It runs on your home server to index and analyze your media such as Movies and TV Shows and presents them in an interface tailored for your media consupmtion needs.
Stars: ✭ 67 (-88.78%)
Mutual labels:  hacktoberfest, database, real-time
Openfoodfacts Server
Open Food Facts database and web interface - 🐪🦋 Perl, CSS and JS coders welcome 😊 For helping in Python, see Robotoff
Stars: ✭ 325 (-45.56%)
Mutual labels:  hacktoberfest, database
Trefle Api
🍀 Trefle is a botanical JSON REST API for plants species, allowing you to search and query over all the registered species, and build the next gardening apps and farming robots.
Stars: ✭ 335 (-43.89%)
Mutual labels:  hacktoberfest, database
Swim
Distributed software platform for building stateful, massively real-time streaming applications.
Stars: ✭ 368 (-38.36%)
Mutual labels:  real-time, distributed-systems
Altair
✨⚡️ A beautiful feature-rich GraphQL Client for all platforms.
Stars: ✭ 3,827 (+541.04%)
Mutual labels:  hacktoberfest, database
Rel
💎 Modern Database Access Layer for Golang - Testable, Extendable and Crafted Into a Clean and Elegant API
Stars: ✭ 317 (-46.9%)
Mutual labels:  hacktoberfest, database
Lbadd
LBADD: An experimental, distributed SQL database
Stars: ✭ 362 (-39.36%)
Mutual labels:  hacktoberfest, database
Yii2 Migration
Yii 2 Migration Creator And Updater
Stars: ✭ 262 (-56.11%)
Mutual labels:  hacktoberfest, database
Cortx
CORTX Community Object Storage is 100% open source object storage uniquely optimized for mass capacity storage devices.
Stars: ✭ 426 (-28.64%)
Mutual labels:  hacktoberfest, distributed-systems
Ergo
a Framework for creating mesh networks using technologies and design patterns of Erlang/OTP in Golang
Stars: ✭ 376 (-37.02%)
Mutual labels:  otp, distributed-systems
Cockroach
CockroachDB - the open source, cloud-native distributed SQL database.
Stars: ✭ 22,700 (+3702.35%)
Mutual labels:  hacktoberfest, database
Trino
Official repository of Trino, the distributed SQL query engine for big data, formerly known as PrestoSQL (https://trino.io)
Stars: ✭ 4,581 (+667.34%)
Mutual labels:  database, distributed-systems
Android Ddp
[UNMAINTAINED] Meteor's Distributed Data Protocol (DDP) for clients on Android
Stars: ✭ 271 (-54.61%)
Mutual labels:  database, real-time
Waltz
Waltz is a quorum-based distributed write-ahead log for replicating transactions
Stars: ✭ 328 (-45.06%)
Mutual labels:  database, distributed-systems
Takeoff
A rapid development environment using docker for convenience.
Stars: ✭ 271 (-54.61%)
Mutual labels:  hacktoberfest, database
5e Database
Database for the D&D 5th Edition API
Stars: ✭ 354 (-40.7%)
Mutual labels:  hacktoberfest, database
Corfudb
A cluster consistency platform
Stars: ✭ 539 (-9.72%)
Mutual labels:  database, distributed-systems
traffic
Massively real-time traffic streaming application
Stars: ✭ 25 (-95.81%)
Mutual labels:  distributed-systems, real-time
transit
Massively real-time city transit streaming application
Stars: ✭ 20 (-96.65%)
Mutual labels:  distributed-systems, real-time

Memento

Build Status Coverage Version License

Simple but Powerful Elixir interface to the Erlang Mnesia Database Mnesia. Memento. Get it?


  • 😀 Easy to Use: Provides a simple & intuitive API for working with Mnesia
  • ⚡️ Real-time: Has extremely fast real-time data searches, even across many nodes
  • 💪 Powerful Queries: on top of Erlang's MatchSpec and QLC, that are much easier to use
  • 📓 Detailed Documentation: and examples for all methods on HexDocs
  • 💾 Persistent: Schema can be coherently kept on disc & in memory
  • 🌐 Distributed: Data can easily be replicated on several nodes
  • 🌀 Atomic: A series of operations can be grouped in to a single atomic transaction
  • 🔍 Focused: Encourages good patterns by omitting dirty calls to the database
  • 🔧 Mnesia Compatible: You can still use Mnesia methods for Schemas and Tables created by Memento
  • ❄️ No Dependencies: Zero external dependencies; only uses the built-in Mnesia module
  • ⛅️ MIT Licensed: Free for personal and commercial use

Memento is an extremely easy-to-use and powerful wrapper in Elixir that makes it intuitive to work with Mnesia, the Erlang Distributed Realtime Database. The original Mnesia API in Erlang is convoluted, unorganized and combined with the complex MatchSpec and QLC query language, is hard to work with in Elixir, especially for beginners. Memento attempts to define a simple API to work with schemas, removing the majority of complexity associated with it.


Installation

Add :memento to your list of dependencies in your Mix file:

def deps do
  [{:memento, "~> 0.3.1"}]
end

If your Elixir version is 1.3 or lower, also add it to your applications list:

def application do
  [applications: [:memento]]
end

It's preferable to only add :memento and not :mnesia along with it. This will ensure that that OTP calls to Mnesia go through the Supervisor spec specified in Memento.


Configuration

It is highly recommended that a custom path to the Mnesia database location is specified, even on the local :dev environment (You can add .mnesia to your .gitignore):

# config/config.exs
config :mnesia,
  dir: '.mnesia/#{Mix.env}/#{node()}'        # Notice the single quotes

Usage

You start by defining a Module as a Memento Table by specifying its attributes, type and other options. At least two attributes are required, where the first one is the primary-key of the table. A simple definition looks like this:

defmodule Blog.Author do
  use Memento.Table, attributes: [:username, :fullname]
end

A slightly more complex definition that uses more options, could look like this:

defmodule Blog.Post do
  use Memento.Table,
    attributes: [:id, :title, :content, :status, :author],
    index: [:status, :author],
    type: :ordered_set,
    autoincrement: true


  # You can also define other methods
  # or helper functions in the module
end

Once you have defined your schemas, you need to create them before you can interact with them:

Memento.Table.create!(Blog.Author)
Memento.Table.create!(Blog.Post)

See the Memento.Table documentation for detailed examples and more information about all the options.


CRUD Operations & Queries

Once a Table has been created, you can perform read/write/delete operations on their records. An API for all of these operations is exposed in the Memento.Query module, but these methods can't be called directly. Instead, they must always be called inside a Memento.Transaction:

Memento.transaction! fn ->
  Memento.Query.all(Blog.Author)
end

# => [
#  %Blog.Author{username: :sye,     fullname: "Sheharyar Naseer"},
#  %Blog.Author{username: :jeanne,  fullname: "Jeanne Bolding"},
#  %Blog.Author{username: :pshore,  fullname: "Paul Shore"},
# ]

For the sake of succinctness, transactions are ignored in most of the examples below, but they are still required. Here's a quick overview of all the basic operations:

# Get all records in a Table
Memento.Query.all(Post)

# Get a specific record by its primary key
Memento.Query.read(Post, id)
Memento.Query.read(Author, username)

# Write a record
Memento.Query.write(%Author{username: :sarah, name: "Sarah Molton"})

# Delete a record by primary key
Memento.Query.delete(Post, id)
Memento.Query.delete(Author, username)

# Delete a record by passing the full object
Memento.Query.delete_record(%Author{username: :pshore, name: "Paul Shore"})

For more complex read operations, Memento exposes a select/3 method that lets you chain conditions using a simplified version of the Erlang MatchSpec. This is what some queries would look like for a Movie table:

  • Get all movies named "Rush":

    Memento.Query.select(Movie, {:==, :title, "Rush"})
    
  • Get all movies directed by Tarantino before the year 2000:

    guards = [
      {:==, :director, "Quentin Tarantino"},
      {:<, :year, 2000},
    ]
    Memento.Query.select(Movie, guards)
    

See Query.select/3 for more information about the guard operators and detailed examples.


Persisting to Disk

Setting up disk persistence in Mnesia has always been a bit weird. It involves stopping the application, creating schemas on disk, restarting the application and then creating the tables with certain options. Here are the steps you need to take to do all of that:

# List of nodes where you want to persist
nodes = [ node() ]

# Create the schema
Memento.stop
Memento.Schema.create(nodes)
Memento.start

# Create your tables with disc_copies (only the ones you want persisted on disk)
Memento.Table.create!(TableA, disc_copies: nodes)
Memento.Table.create!(TableB, disc_copies: nodes)
Memento.Table.create!(TableC)

This needs to be done only once and not every time the application starts. It also makes sense to create a helper function or mix task that does this for you. You can see a sample implementation here.


Roadmap

  • [x] Memento
    • [x] start/stop
    • [x] info
    • [x] system_info
    • [ ] Application
    • [ ] Config Vars
  • [x] Memento.Table
    • [x] Create/Delete helpers
    • [x] clear_table
    • [x] table_info
    • [ ] wait
    • [ ] Ecto-like DSL
    • [ ] Migration Support
  • [x] Memento.Query
    • [x] Integration with Memento.Table
    • [x] match/select
    • [x] read/write/delete
    • [ ] first/next/prev/all_keys
    • [ ] test matchspec
    • [ ] continue/1 for select continuations
    • [x] autoincrement
    • [ ] Helper use macro
  • [x] Memento.Transaction
    • [x] Simple/Synchronous
    • [x] Bang versions
    • [x] inside?
    • [x] abort
    • [ ] Lock Helpers
  • [x] Memento.Schema
    • [x] create/delete
    • [x] print (schema/1)
  • [ ] Memento.Collection
    • [ ] Easy Helpers
    • [ ] Custom DSL
  • [ ] Mix Tasks

FAQ

1. Why Memento/Mnesia?

In most applications, some kind of data storage mechanism is needed, but this usually means relying on some sort of external dependency or program. Memento should be used in situations when it might not always make sense in an Application to do this (e.g. the data is ephemeral, the project needs to be kept light-weight, you need a simple data store that persists across application restarts, data-code decoupling is not important etc.).

2. When shouldn't I use Memento/Mnesia?

Like mentioned in the previous point, Memento/Mnesia has specific use-cases and it might not always make sense to use it. This is usually when you don't want to couple your code and database, and want to allow independent or external accesses to transformation of your data. In such circumstances, you should always prefer using some other datastore (like Redis, Postgres, etc.).

3. Isn't there already an 'Amnesia' library?

I've been a long-time user of the Amnesia package, but with the recent releases of Elixir (1.5 & above), the library has started to show its age. Amnesia's dependence on the the exquisite package has caused a lot of compilation problems, and it's complex macro-intensive structure hasn't made it easy to fix them either. The library itself doesn't even compile in Elixir 1.7+ so I finally decided to write my own after I desperately needed to update my Mnesia-based projects.

Memento is meant to be an extremely lightweight wrapper for Mnesia, providing a very easy set of helpers and forcing good decisions by avoiding the "dirty" methods.

4. Are there any other projects that are using Memento?

Memento is a new package so there aren't many Open Source examples available. Que is another library that uses Memento for background job processing and storing the state of these Jobs. If your project uses Memento, feel free to send in a pull-request so it can be mentioned here.


Contributing

  • Fork, Enhance, Send PR
  • Lock issues with any bugs or feature requests
  • Implement something from Roadmap
  • Spread the word ❤️

License

This package is available as open source under the terms of the MIT License.


Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].