Skip to content

Commit

Permalink
Initial commit.
Browse files Browse the repository at this point in the history
All working as it was built in another project.
  • Loading branch information
jnunemaker committed Jan 26, 2011
0 parents commit e13e43a
Show file tree
Hide file tree
Showing 11 changed files with 257 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pkg/*
*.gem
.bundle
12 changes: 12 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
source "http://rubygems.org"

# Specify your gem's dependencies in adapter-memcached.gemspec
gemspec

group(:development) do
gem 'rspec', '~> 2.3'
gem 'log_buddy', '~> 0.5.0'
gem 'timecop', '~> 0.3.5'
gem 'i18n', '0.5.0'
gem 'activesupport', '~> 3', :require => 'active_support'
end
38 changes: 38 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
PATH
remote: .
specs:
adapter-memcached (1.0)
adapter (~> 0.5)
memcached (~> 1.0.2)

GEM
remote: http://rubygems.org/
specs:
activesupport (3.0.3)
adapter (0.5.1)
diff-lcs (1.1.2)
i18n (0.5.0)
log_buddy (0.5.0)
memcached (1.0.2)
rspec (2.4.0)
rspec-core (~> 2.4.0)
rspec-expectations (~> 2.4.0)
rspec-mocks (~> 2.4.0)
rspec-core (2.4.0)
rspec-expectations (2.4.0)
diff-lcs (~> 1.1.2)
rspec-mocks (2.4.0)
timecop (0.3.5)

PLATFORMS
ruby

DEPENDENCIES
activesupport (~> 3)
adapter (~> 0.5)
adapter-memcached!
i18n (= 0.5.0)
log_buddy (~> 0.5.0)
memcached (~> 1.0.2)
rspec (~> 2.3)
timecop (~> 0.3.5)
7 changes: 7 additions & 0 deletions Rakefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
require 'bundler'
Bundler::GemHelper.install_tasks

require 'rspec/core/rake_task'
RSpec::Core::RakeTask.new

task :default => :spec
22 changes: 22 additions & 0 deletions adapter-memcached.gemspec
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# -*- encoding: utf-8 -*-
$:.push File.expand_path("../lib", __FILE__)
require "adapter/memcached/version"

Gem::Specification.new do |s|
s.name = "adapter-memcached"
s.version = Adapter::Memcached::VERSION
s.platform = Gem::Platform::RUBY
s.authors = ["TODO: Write your name"]
s.email = ["TODO: Write your email address"]
s.homepage = ""
s.summary = %q{TODO: Write a gem summary}
s.description = %q{TODO: Write a gem description}

s.files = `git ls-files`.split("\n")
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
s.require_paths = ["lib"]

s.add_dependency 'adapter', '~> 0.5'
s.add_dependency 'memcached', '~> 1.0.2'
end
25 changes: 25 additions & 0 deletions examples/memcached.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
require 'rubygems'
require 'pathname'

root_path = Pathname(__FILE__).dirname.join('..').expand_path
lib_path = root_path.join('lib')
$:.unshift(lib_path)

require 'adapter/memcached'

client = Memcached.new('localhost:11211', :namespace => 'adapter_example')
adapter = Adapter[:memcached].new(client)
adapter.clear

adapter.write('foo', 'bar')
puts 'Should be bar: ' + adapter.read('foo').inspect

adapter.delete('foo')
puts 'Should be nil: ' + adapter.read('foo').inspect

adapter.write('foo', 'bar')
adapter.clear
puts 'Should be nil: ' + adapter.read('foo').inspect

puts 'Should be bar: ' + adapter.fetch('foo', 'bar')
puts 'Should be bar: ' + adapter.read('foo')
56 changes: 56 additions & 0 deletions lib/adapter/memcached.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
require 'adapter'
require 'memcached'

module Adapter
module Memcached
def read(key)
decode(client.get(key_for(key)))
rescue ::Memcached::NotFound
end

def write(key, value)
client.set(key_for(key), encode(value))
end

def delete(key)
read(key).tap { client.delete(key_for(key)) }
rescue ::Memcached::NotFound
end

def clear
client.flush
end

def lock(name, options={}, &block)
key = name.to_s
start = Time.now
lock_acquired = false
expiration = options.fetch(:expiration, 1)
timeout = options.fetch(:timeout, 5)

while (Time.now - start) < timeout
begin
client.add(key, 'locked', expiration)
lock_acquired = true
break
rescue ::Memcached::NotStored
sleep 0.1
end
end

raise(Adapter::LockTimeout.new(name, timeout)) unless lock_acquired

begin
yield
ensure
delete(key)
end
end

def key_for(key)
[super].pack("m").strip
end
end
end

Adapter.define(:memcached, Adapter::Memcached)
5 changes: 5 additions & 0 deletions lib/adapter/memcached/version.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module Adapter
module Memcached
VERSION = "1.0"
end
end
1 change: 1 addition & 0 deletions log/test.log
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Logfile created on Tue Jan 25 21:59:54 -0500 2011 by logger.rb
26 changes: 26 additions & 0 deletions spec/helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
$:.unshift(File.expand_path('../../lib', __FILE__))

require 'rubygems'
require 'bundler'

Bundler.require(:default, :development)

require 'pathname'
require 'logger'

root_path = Pathname(__FILE__).dirname.join('..').expand_path
lib_path = root_path.join('lib')
log_path = root_path.join('log')
log_path.mkpath

require 'adapter/spec/an_adapter'
require 'adapter/spec/marshal_adapter'
require 'adapter/spec/json_adapter'
require 'adapter/spec/types'

logger = Logger.new(log_path.join('test.log'))
LogBuddy.init(:logger => logger)

Rspec.configure do |c|

end
62 changes: 62 additions & 0 deletions spec/memcached_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
require 'helper'
require 'adapter/memcached'

describe "Memcached adapter" do
before do
@client = Memcached.new('localhost:11211', :namespace => 'adapter_spec')
@adapter = Adapter[:memcached].new(@client)
@adapter.clear
end

let(:adapter) { @adapter }
let(:client) { @client }

it_should_behave_like 'a marshaled adapter'

describe "#lock" do
let(:lock_key) { :add_game }
let(:lock_value) { 'locked' }

it "defaults expiration to 1" do
client.should_receive(:add).with(lock_key.to_s, lock_value, 1)
adapter.lock(lock_key) { }
end

it "allows setting expiration" do
client.should_receive(:add).with(lock_key.to_s, lock_value, 5)
adapter.lock(lock_key, :expiration => 5) { }
end

describe "with no existing lock" do
it "acquires lock, performs block, and clears lock" do
result = false
adapter.lock(lock_key) { result = true }

result.should be_true
adapter.read(lock_key).should be_nil
end
end

describe "with lock set" do
it "waits for unlock, performs block, and clears lock" do
result = false
client.add(lock_key.to_s, lock_value, 1)
adapter.lock(lock_key, :timeout => 2) { result = true }

result.should be_true
adapter.read(lock_key).should be_nil
end
end

describe "with lock set that does not expire before timeout" do
it "raises lock timeout error" do
result = false
client.add(lock_key.to_s, lock_value, 2)

lambda do
adapter.lock(lock_key, :timeout => 1) { result = true }
end.should raise_error(Adapter::LockTimeout, 'Timeout on lock add_game exceeded 1 sec')
end
end
end
end

0 comments on commit e13e43a

Please sign in to comment.