Skip to content
This repository has been archived by the owner on May 29, 2020. It is now read-only.

Commit

Permalink
Merge bc9fbaf into 18cf147
Browse files Browse the repository at this point in the history
  • Loading branch information
ottbot committed Aug 6, 2013
2 parents 18cf147 + bc9fbaf commit 3a9f7dd
Show file tree
Hide file tree
Showing 18 changed files with 415 additions and 198 deletions.
2 changes: 1 addition & 1 deletion Gemfile
Expand Up @@ -3,6 +3,6 @@ source 'https://rubygems.org'
# Specify your gem's dependencies in virsandra.gemspec

gem 'coveralls', require: false
gem "cassandra-cql", :git => "git://github.com/ottbot/cassandra-cql", :branch => "1.2-set-consistency"


gemspec
92 changes: 72 additions & 20 deletions lib/virsandra.rb
@@ -1,37 +1,89 @@
require "virtus"
require "cassandra-cql/1.2"
require 'virtus'
require 'cql'
require 'simple_uuid'
require 'forwardable'


require "virsandra/version"
require 'virsandra/errors'
require "virsandra/configuration"
require "virsandra/connection"
require "virsandra/cql_value"
require "virsandra/query"
require "virsandra/model_query"
require "virsandra/model"

module Virsandra

extend Configuration

class << self
extend Forwardable
def_delegator :connection, :execute
def configuration
Thread.current[:configuration] ||= Virsandra::Configuration.new
end

def connection
@connection = Connection.new(self) if dirty?
@connection
def configure
yield configuration
end

def dirty?
return true if @connection.nil?
@connection.options != self.to_hash
def connection
if dirty?
disconnect!
Thread.current[:connection] = Virsandra::Connection.new(configuration)
configuration.accept_changes
end
Thread.current[:connection]
end

def disconnect!
if @connection && @connection.handle
@connection.disconnect!
if Thread.current[:connection].respond_to?(:disconnect!)
Thread.current[:connection].disconnect!
end
@connection = nil
Thread.current[:connection] = nil
end

def reset!
configuration.reset!
end

def reset_configuration!
Thread.current[:configuration] = nil
end

def consistency
configuration.consistency
end

def keyspace
configuration.keyspace
end

def servers
configuration.servers
end

def consistency=(value)
configuration.consistency = value
end

def keyspace=(value)
configuration.keyspace = value
end

def servers=(value)
configuration.servers = value
end

def execute(query)
connection.execute(query)
end

private

def dirty?
Thread.current[:connection].nil? || configuration.changed?
end

end
end



require "virsandra/connection"
require "virsandra/cql_value"
require "virsandra/query"
require "virsandra/model_query"
require "virsandra/model"
59 changes: 37 additions & 22 deletions lib/virsandra/configuration.rb
@@ -1,32 +1,26 @@
module Virsandra
class ConfigurationError < Exception; ; end

module Configuration

class Configuration
OPTIONS = [
:consistency,
:keyspace,
:servers,
:thrift_options,
:consistency,
:cql_version
]
].freeze

DEFAULT_OPTION_VALUES = {
servers: "127.0.0.1",
consistency: :quorum
}.freeze

attr_accessor *OPTIONS

def self.extended(base)
base.reset!
def initialize(options = {})
reset!
use_options(options || {})
accept_changes
end

def reset!
self.servers = '127.0.0.1:9160'
self.cql_version = '3.0.0'
self.consistency = :quorum
self.thrift_options = {retries: 5, connect_timeout: 10, timeout: 10}
self.keyspace = nil
end

def configure
yield self
use_options(DEFAULT_OPTION_VALUES)
end

def validate!
Expand All @@ -35,12 +29,33 @@ def validate!
end
end

def accept_changes
@old_hash = hash
end

def to_hash
OPTIONS.reduce({}) do |settings, option|
settings[option] = self.send(option)
settings
OPTIONS.each_with_object({}) do |attr, settings|
settings[attr] = send(attr)
end
end

def changed?
hash != @old_hash
end

def hash
to_hash.hash
end

private

def use_options(options)
options.each do |key, value|
if OPTIONS.include?(key)
send(:"#{key}=", value)
end
end
end
end

end
23 changes: 14 additions & 9 deletions lib/virsandra/connection.rb
Expand Up @@ -3,21 +3,26 @@ class Connection

extend Forwardable

attr_reader :handle, :options

def initialize(options)
options.validate!
@options = options.to_hash
attr_reader :handle, :config

def initialize(config)
@config = config
config.validate!
connect!
end

def connect!
cql_options = @options.select {|k| [:keyspace, :cql_version, :consistency].include?(k) }
@handle = Cql::Client.connect(hosts: @config.servers)
@handle.use(@config.keyspace)
@handle
end

def disconnect!
@handle.close
end

@handle = CassandraCQL::Database.new(@options[:servers],
cql_options,
@options[:thrift_options])
def execute(query, consistency = nil)
@handle.execute(query, consistency || config.consistency)
end

# Delegate to CassandraCQL::Database handle
Expand Down
15 changes: 10 additions & 5 deletions lib/virsandra/cql_value.rb
Expand Up @@ -12,18 +12,23 @@ def initialize(value)
end

def to_cql
case value
when Numeric
value.to_s
when SimpleUUID::UUID
if value.respond_to?(:to_guid)
value.to_guid
else
elsif should_escape?(value)
"'#{escape(value)}'"
else
value.to_s
end
end

private

def should_escape?(value)
!![String, Symbol, Time, Date].detect do |klass|
value.is_a?(klass)
end
end

def escape(str)
str = str.to_s.gsub(/'/,"''")
str.force_encoding('ASCII-8BIT')
Expand Down
3 changes: 3 additions & 0 deletions lib/virsandra/errors.rb
@@ -0,0 +1,3 @@
module Virsandra
class ConfigurationError < ArgumentError; ; end
end
3 changes: 2 additions & 1 deletion lib/virsandra/model_query.rb
Expand Up @@ -40,7 +40,8 @@ def valid_search_params?(params)

def query_enumerator(query)
Enumerator.new do |yielder|
query.execute.each do |row|
rows = query.execute
rows.each do |row|
record = @model.new(row.to_hash)
yielder.yield record
end
Expand Down
3 changes: 2 additions & 1 deletion lib/virsandra/query.rb
Expand Up @@ -56,6 +56,7 @@ def values *args
end

def execute

@row = Virsandra.execute(self.to_s)
end

Expand All @@ -72,7 +73,7 @@ def raw_query
end

def fetch_with_symbolized_keys
row_hash = @row && @row.fetch_hash
row_hash = @row && @row.first
return {} unless row_hash

Hash[row_hash.map{|(k,v)| [k.to_sym,v]}]
Expand Down
2 changes: 1 addition & 1 deletion lib/virsandra/version.rb
@@ -1,3 +1,3 @@
module Virsandra
VERSION = "0.0.1"
VERSION = "0.5.0"
end
62 changes: 62 additions & 0 deletions spec/feature_helper.rb
@@ -0,0 +1,62 @@
require 'spec_helper'

TEST_KEYSPACE = "virtest"

module IntegrationTestHelper
def create_keyspace
Virsandra.keyspace = 'system'
Virsandra.execute("CREATE KEYSPACE #{TEST_KEYSPACE} WITH REPLICATION = {'class': 'SimpleStrategy', 'replication_factor': 1}")
Virsandra.reset!
end

def create_companies_table
cql = <<-CQL
CREATE TABLE companies (
id uuid,
name text,
score int,
founder text,
founded int,
PRIMARY KEY (id, score))
CQL
Virsandra.keyspace = TEST_KEYSPACE
Virsandra.execute(cql)
end

def drop_keyspace
Virsandra.reset!
Virsandra.keyspace = 'system'
Virsandra.execute("DROP KEYSPACE #{TEST_KEYSPACE}")
end

def build_up
begin
create_keyspace
create_companies_table
rescue Cql::QueryError
drop_keyspace

if defined?(retried)
raise $!
else
retried = true
retry
end
end
end
end



RSpec.configure do |config|

config.include(IntegrationTestHelper)

config.before do
if example.metadata[:integration]
build_up
Virsandra.reset!
Virsandra.keyspace = TEST_KEYSPACE
end
end
end
13 changes: 13 additions & 0 deletions spec/integration/virsandra_spec.rb
@@ -0,0 +1,13 @@
require 'feature_helper'

describe "Virsandra", integration: true do

it "return connection to server" do
Virsandra.connection.should_not be_nil
end

it "allows to disconnect" do
Virsandra.connection.should_receive(:disconnect!).and_call_original
Virsandra.disconnect!
end
end

0 comments on commit 3a9f7dd

Please sign in to comment.