key_value 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/Readme.md CHANGED
@@ -1,4 +1,4 @@
1
- Abuse Sql database as Key-Value Store
1
+ Abuse Sql database as Key-Value Store that can be [750k-qps-crazy-fast](http://yoshinorimatsunobu.blogspot.com/2010/10/using-mysql-as-nosql-story-for.html) via HandlerSocket
2
2
 
3
3
  Install
4
4
  =======
@@ -6,12 +6,12 @@ Install
6
6
 
7
7
  Migration
8
8
  =========
9
- `rails g migration create_key_value`
9
+ `rails g migration create_key_value` and paste in:
10
10
 
11
11
  class CreateKeyValue < ActiveRecord::Migration
12
12
  def self.up
13
- create_table :key_values do |t|
14
- t.string :key, :null => false
13
+ create_table :key_values, :id => false do |t|
14
+ t.string :key, :null => false, :primary => true
15
15
  t.text :value, :null => false
16
16
  end
17
17
  add_index :key_values, :key, :unique => true
@@ -43,10 +43,10 @@ Usage
43
43
  # cache
44
44
  KeyValue.cache('xxx'){ ..something expensive.. }
45
45
 
46
- HandlerSocket for [750k-qps](http://yoshinorimatsunobu.blogspot.com/2010/10/using-mysql-as-nosql-story-for.html),
47
- [Ubuntu natty guide](http://grosser.it/2011/05/14/installing-mysql-handlersocket-in-ubuntu-natty-for-ruby/)
46
+ HandlerSocket ([Ubuntu natty guide](http://grosser.it/2011/05/14/installing-mysql-handlersocket-in-ubuntu-natty-for-ruby/)):
48
47
 
49
- KeyValue.handler_socket = {:host => '127.0.0.1', :port=>'9998', :database => 'foo_development'}
48
+ KeyValue.handler_socket = true
49
+ # or Hash with any of these keys :host :port :database :timeout :listen_backlog :sndbuf :rcvbuf
50
50
 
51
51
  # all read requests use HandlerSocket
52
52
  KeyValue['xxx'] # -> same as before but faster :)
@@ -54,9 +54,7 @@ HandlerSocket for [750k-qps](http://yoshinorimatsunobu.blogspot.com/2010/10/usin
54
54
  TODO
55
55
  ====
56
56
  - nice error handling for HandlerSocket
57
- - reuse host/database from normal connection for HandlerSocket
58
57
  - HandlerSocket write support
59
- - use 'key' column as primary key <-> any problems with that ?
60
58
  - make test database configurable
61
59
 
62
60
  Authors
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.0
1
+ 0.3.0
data/key_value.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{key_value}
8
- s.version = "0.2.0"
8
+ s.version = "0.3.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Roman Heinrich", "Michael Grosser"]
12
- s.date = %q{2011-05-14}
12
+ s.date = %q{2011-05-15}
13
13
  s.email = %q{michael@grosser.it}
14
14
  s.files = [
15
15
  "Gemfile",
data/lib/key_value.rb CHANGED
@@ -4,8 +4,8 @@ class KeyValue < ActiveRecord::Base
4
4
  HS_DEFAULT_CONFIG = {:port => '9998'}
5
5
  HS_INDEX = 31234 # just some high number...
6
6
  VERSION = File.read( File.join(File.dirname(__FILE__),'..','VERSION') ).strip
7
- validates_presence_of :key
8
7
 
8
+ set_primary_key :key
9
9
  serialize :value
10
10
 
11
11
  cattr_accessor :handler_socket
@@ -18,7 +18,7 @@ class KeyValue < ActiveRecord::Base
18
18
 
19
19
  def self.get(key)
20
20
  if handler_socket
21
- hs_connection.open_index(HS_INDEX, handler_socket[:database], 'key_values', 'index_key_values_on_key', 'value')
21
+ open_key_index
22
22
  result = hs_connection.execute_single(HS_INDEX, '=', [key])
23
23
  return unless result = result[1][0]
24
24
  YAML.load(result[0])
@@ -31,7 +31,10 @@ class KeyValue < ActiveRecord::Base
31
31
  if value.nil?
32
32
  KeyValue.delete_all(:key => key)
33
33
  else
34
- record = KeyValue.find_by_key(key) || KeyValue.new(:key => key)
34
+ unless record = KeyValue.find_by_key(key)
35
+ record = KeyValue.new
36
+ record.key = key # no mass assignment on primary key
37
+ end
35
38
  record.value = value
36
39
  record.save!
37
40
  value
@@ -63,9 +66,18 @@ class KeyValue < ActiveRecord::Base
63
66
  private
64
67
 
65
68
  def self.hs_connection
66
- @@hs_connection ||= begin
69
+ @hs_connection ||= begin
67
70
  require 'handlersocket'
68
- HandlerSocket.new(HS_DEFAULT_CONFIG.merge(handler_socket).slice(:host, :port))
71
+ HandlerSocket.new(hs_connection_config)
69
72
  end
70
73
  end
74
+
75
+ def self.hs_connection_config
76
+ given = (handler_socket == true ? {} : handler_socket)
77
+ HS_DEFAULT_CONFIG.merge(connection_pool.spec.config.merge(given))
78
+ end
79
+
80
+ def self.open_key_index
81
+ @open_key_index ||= hs_connection.open_index(HS_INDEX, hs_connection_config[:database], table_name, "index_#{table_name}_on_key", 'value')
82
+ end
71
83
  end
@@ -104,7 +104,7 @@ describe KeyValue do
104
104
  if ENV['DB'] == 'mysql'
105
105
  describe 'with handlersocket' do
106
106
  before do
107
- KeyValue.handler_socket = {:host => '127.0.0.1', :port => '9998', :database => 'key_values_test'}
107
+ KeyValue.handler_socket = true
108
108
  KeyValue.delete_all
109
109
  end
110
110
 
@@ -123,6 +123,26 @@ describe KeyValue do
123
123
  KeyValue.should_not_receive(:find_by_key)
124
124
  KeyValue['xxx'].should == false
125
125
  end
126
+
127
+ it "uses defaults" do
128
+ KeyValue.send(:hs_connection_config).except(:username, :password).should == {
129
+ :flags=>2,
130
+ :port=>"9998",
131
+ :adapter=>"mysql2",
132
+ :database=>"key_values_test"
133
+ }
134
+ end
135
+
136
+ it "merges in my given settings" do
137
+ KeyValue.handler_socket = {:port => '123'}
138
+ KeyValue.send(:hs_connection_config).except(:username, :password).should == {
139
+ :flags=>2,
140
+ :port=>"123",
141
+ :adapter=>"mysql2",
142
+ :database=>"key_values_test"
143
+ }
144
+
145
+ end
126
146
  end
127
147
  else
128
148
  puts 'not running HandlerSocket specs'
data/spec/spec_helper.rb CHANGED
@@ -19,8 +19,8 @@ end
19
19
  ActiveRecord::Schema.define(:version => 1) do
20
20
  drop_table :key_values rescue nil
21
21
 
22
- create_table :key_values do |t|
23
- t.string :key, :null => false
22
+ create_table :key_values, :id => false do |t|
23
+ t.string :key, :null => false,:primary => true
24
24
  t.text :value, :null => false
25
25
  end
26
26
  add_index :key_values, :key, :unique => true
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: key_value
3
3
  version: !ruby/object:Gem::Version
4
- hash: 23
4
+ hash: 19
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
- - 2
8
+ - 3
9
9
  - 0
10
- version: 0.2.0
10
+ version: 0.3.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Roman Heinrich
@@ -16,7 +16,7 @@ autorequire:
16
16
  bindir: bin
17
17
  cert_chain: []
18
18
 
19
- date: 2011-05-14 00:00:00 +02:00
19
+ date: 2011-05-15 00:00:00 +02:00
20
20
  default_executable:
21
21
  dependencies:
22
22
  - !ruby/object:Gem::Dependency