DpStmMap
Implementation of a distributed and persistent Map with Software Transactional Memory (STM) semantics.
Installation
Add this line to your application's Gemfile:
gem 'dp_stm_map'
And then execute:
$ bundle
Or install it yourself as:
$ gem install dp_stm_map
Comprehensive defintion
Implementation of a distributed and persistent Map with Software Transactional Memory (STM) semantics.
What is it?
Implementation of a hash map (dp_stm_map) with ACID transactional updates.
Offers a subset of map (Hash) operations
:[], :[]= and :has_key?
Persistent
Unlike data stored in the Hash, data stored in dp_stm_map will survive a restart of RVM.
Distributed
More than one RVM can connect to a central transaction manager (dp_stm_manager) that coordinates transactions for the same dp_stm_map. Every RVM can have its own local view of the current state of the map, making reading operations of dp_stm_map very scalable.
What is so special about it?
Every RVM will receive notification on changes in the map. This makes dp_stm_map great foundation for a distributed Event-driven architecture: Think of one RVM handling web traffic, another indexing persisted state and offering RESTful search service.
Usage
Manager
to start the central transaction manager execute:
$ dp_stm_manager.rb -s
Client
require 'dp_stm_map'
client=DpStmMap::DistributedPersistentStmMap.new host,port,'storage' client.start
Updating map within a transaction
client.atomic do |tx| tx['key'] = 'value' end
Read only transactions
value=client.atomic_read{ |tx| tx['key'] }
Adding a transaction listener
client.on_atomic do |change| # change is map containing all value transitions of one transaction: # e.g. => [nil,'value1'], 'key2' => ['old_value_2','new_value2'] change.each_pair do | k, (old_value, new_value) | update_index k, new_value end end
Adding a transaction validator - will be executed before transaction is passed on to transaction manager
client.validate_atomic do |change| # change is map containing all value transitions of one transaction: # e.g. => [nil,'value1'], 'key2' => ['old_value_2','new_value2'] change.each_pair do | k, (old_value, new_value) |
# exception will abort (roll back) the transaction and will be raised as result of executing :atomic method
raise "new value is invalid" if new_value != 'valid_new_value'
end
end
Using object store wrapper (stores Ruby objects in dp_stm_map by serializing as YAML strings)
object_client=DpStmMap::ObjectStore.new client
# all transaction, notification and validation methods from dp_stm_map are available to ObjectStore
object_client.atomic do |tx| user=User.new user.username="admin" tx[:user, "admin"]=user end
user=object_client.atomic_read { |tx| tx[:user, "admin"] }
object_client.validate_atomic do |change|
Contributing
- Fork it
- Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am 'Add some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create new Pull Request