Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
This is a sample patch for three dm gems - data_objects, do_postgres, and dm-postgres-adapter. It is not ready to be applied, since it is currently unspecced and untested. The purpose of this patch is to solicit feedback as to the architecture, to ensure
require 'dm-transactions/adapters/dm-do-adapter'
module DataMapper
class Transaction
module PostgresAdapter
include DataObjectsAdapter
# Produces a fresh transaction primitive for this Adapter. Fake nested
# transactions by using save points.
# Used by Transaction to perform its various tasks.
# @return [Object]
# a new Object that responds to :close, :begin, :commit,
# and :rollback,
# @api private
def transaction_primitive
if current_transaction
DataObjects::SavePoint.create_for_uri(normalized_uri, current_connection)
require 'digest'
require 'digest/sha2'
# JUSTIFY: Why create a new data object type for save points?
# A save point is analgous to a transaction, and a transaction has its own
# DataObject. Save points are supported by [] do databases, and [are|are
# not] part of the SQL spec.
module DataObjects
# JUSTIFY: Why not inherit from Transaction?
# Even though they share a lot of behaviour, a SavePoint does not satisfy
# LSP for transaction, both because it can't be used in place of a transaction
# (save points require you to be inside a transaction), and as such because
# of the required for the extra connection parameter.
# There is a case to be made for refactoring the common behaviour into a mixin.
class SavePoint
# The host name. Note, this relies on the host name being configured and resolvable using DNS
HOST = "#{Socket::gethostbyname(Socket::gethostname)[0]}" rescue "localhost"
@@counter = 0
# The connection object allocated for this transaction
attr_reader :connection
# A unique ID for this transaction
attr_reader :id
# Instantiate the Transaction subclass that's appropriate for this uri scheme
def self.create_for_uri(uri, connection)
uri = uri.is_a?(String) ? URI::parse(uri) : uri
# JUSTIFY: Why passing in the connection? Transaction doesn't need this...
# Unlike the similar Transaction primitive, which is only created once
# per connection and reused for each transaction, this primitive will
# be created once for each save point, since each save point requires
# its own unique identify. As a result, the extra connection paramater
# is required to allow the existing connection to be reused.
def initialize(uri, connection)
@connection = connection
@id = Digest::SHA256.hexdigest("#{HOST}:#{$$}:#{}:#{@@counter += 1}")
def begin
run %{SAVEPOINT "#{@id}"}
def commit
run %{RELEASE SAVEPOINT "#{@id}"}
def rollback
# JUSTIFY: Transaction doesn't have this extract method refactoring, why here?
# Because I see no reason for this not also to be applied to Transaction
def run(cmd)

This comment has been minimized.

Show comment Hide comment

jpr5 Dec 16, 2010

This has been effectively merged in:

jpr5 commented Dec 16, 2010

This has been effectively merged in:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment