Class: Palsy
- Inherits:
-
SQLite3::Database
- Object
- SQLite3::Database
- Palsy
- Includes:
- Singleton
- Defined in:
- lib/palsy.rb,
lib/palsy/basic/map.rb,
lib/palsy/basic/set.rb,
lib/palsy/basic/list.rb,
lib/palsy/basic/object.rb,
lib/palsy/basic/generic.rb,
lib/palsy/basic/collection.rb
Overview
Present ruby core data structures in a manner similar to perl’s tie backed by a SQLite database. Intended to be as simple as possible, sacrificing performance and flexibility to do so.
It is not a 1:1 emulation of tie, as ruby cannot support this. What it does do is provide a convincing enough facsimile by emulating the interface, and making it easy to convert to native ruby types when that’s not enough.
This library is completely unapologetic with regards to how little it does or how slow it does things.
All writes are fully consistent, which is something SQLite gives us. Reads always hit the database. This allows us to reason more clearly about how our data persists, even in concurrent models where shared state can get very complicated to use.
Defined Under Namespace
Classes: Collection, Generic, List, Map, Object, Set
Constant Summary collapse
- VERSION =
Palsy’s version, as a string.
PalsyVersion
Class Attribute Summary collapse
-
.database ⇒ Object
The name of the database Palsy will manipulate.
Class Method Summary collapse
-
.change_db(db_name) ⇒ Object
Given a db name, assigns that to Palsy and initiates a reconnection.
-
.close ⇒ Object
Closes the SQLite database.
-
.reconnect ⇒ Object
Initiates a reopening of the SQLite database.
Instance Method Summary collapse
-
#connect ⇒ Object
Opens the database.
-
#execute_t(query, args = [], &block) ⇒ Object
Execute this query in an exclusive transaction.
-
#initialize ⇒ Palsy
constructor
Initializer.
-
#no_lock ⇒ Object
Override the explicit lock for the current thread.
-
#reconnect ⇒ Object
Initiates a reopening of the SQLite database.
-
#with_t ⇒ Object
Start a mutex-wrapped exclusive transaction, then execute the block.
Constructor Details
#initialize ⇒ Palsy
Initializer. Since Palsy is a proper Ruby singleton, calling Palsy.instance will run this the first time, but calling this directly is not advised. Use the Palsy class methods like Palsy.change_db, or set Palsy.database= before working with the rest of the library.
70 71 72 73 |
# File 'lib/palsy.rb', line 70 def initialize @palsy_lock = Mutex.new super(connect) end |
Class Attribute Details
.database ⇒ Object
The name of the database Palsy will manipulate. Set this before using Palsy. Look at Palsy.change_db for a better way to swap DB’s during runtime.
35 36 37 |
# File 'lib/palsy.rb', line 35 def database @database end |
Class Method Details
.change_db(db_name) ⇒ Object
Given a db name, assigns that to Palsy and initiates a reconnection.
Note that existing Palsy objects will immediately start working against this new database, and expect everything needed to read the data to exist, namely the tables they’re keyed against.
45 46 47 48 |
# File 'lib/palsy.rb', line 45 def self.change_db(db_name) self.database = db_name self.reconnect end |
.close ⇒ Object
Closes the SQLite database.
60 61 62 |
# File 'lib/palsy.rb', line 60 def self.close self.instance.close end |
.reconnect ⇒ Object
Initiates a reopening of the SQLite database.
53 54 55 |
# File 'lib/palsy.rb', line 53 def self.reconnect self.instance.reconnect end |
Instance Method Details
#connect ⇒ Object
Opens the database. Note that this is a no-op unless Palsy.database= is set.
87 88 89 90 91 |
# File 'lib/palsy.rb', line 87 def connect if self.class.database SQLite3::Database.new(self.class.database) end end |
#execute_t(query, args = [], &block) ⇒ Object
Execute this query in an exclusive transaction.
155 156 157 158 159 160 161 |
# File 'lib/palsy.rb', line 155 def execute_t(query, args=[], &block) result = nil with_t { result = execute(query, args, &block) } return result end |
#no_lock ⇒ Object
Override the explicit lock for the current thread. For things that generate queries, will not attempt to acquire a mutex, will not attempt to run a transaction. Will just run the block. See #with_t for information on lock semantics.
For Ruby 2.0 users and above: If you wrap your palsy operations in #no_lock on the current thread, #with_t will not try to use a mutex lock or transaction.
This is useful if you want to use palsy in a signal handler:
trap("INFO") do
Palsy.instance.no_lock do
some_palsy_thing
end
end
The caveat is that any writes done in this region will not be isolated and will likely cause problems.
113 114 115 116 117 118 119 |
# File 'lib/palsy.rb', line 113 def no_lock retval = nil Thread.current[:palsy_no_lock] = true retval = yield Thread.current[:palsy_no_lock] = false return retval end |
#reconnect ⇒ Object
Initiates a reopening of the SQLite database. Instance method that Palsy.reconnect uses.
79 80 81 82 |
# File 'lib/palsy.rb', line 79 def reconnect close rescue nil __setobj__(connect) end |
#with_t ⇒ Object
Start a mutex-wrapped exclusive transaction, then execute the block. If we’re already the owner of the transaction, just execute.
This is used by most things in Palsy. If you want to step around the lock (necessary for specific situations, and has certain caveats), take a look at #no_lock.
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 |
# File 'lib/palsy.rb', line 129 def with_t result = nil tc = Thread.current if tc[:lock] or tc[:palsy_no_lock] result = yield else @palsy_lock.synchronize do begin tc[:lock] = @palsy_lock transaction(:exclusive) { result = yield } rescue StandardError => e rollback if transaction_active? raise e ensure tc[:lock] = nil end end end return result end |