coderrr-memcache_queue 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.markdown ADDED
File without changes
@@ -0,0 +1,112 @@
1
+ require 'rubygems'
2
+ require 'memcache'
3
+
4
+ # It's your job to catch any signals relating to process termination
5
+ # (INT, TERM, etc.) and call the shutdown method on each worker. If
6
+ # this isn't done you run the risk of losing messages.
7
+ class MemcacheQueue
8
+ class ShutdownError < StandardError; end
9
+
10
+ attr_accessor :add_timeout
11
+
12
+ def initialize(name, *args)
13
+ @name = name or raise ArgumentError, "Must specify a unique name for each worker"
14
+ @client = MemCache.new *args
15
+ @first_key = state(:get, name)
16
+ @add_timeout = 10
17
+ end
18
+
19
+ def create_queue
20
+ @client.add('latest_added', '0', 0, true)
21
+ @client.add('latest_read', '0', 0, true)
22
+ end
23
+
24
+ # ! lost message potential !
25
+ # If it takes more than add_timeout seconds from the time incr
26
+ # returns to the time the message is add()ed to memcache the message _could_
27
+ # be lost.
28
+ def add_msg(msg)
29
+ raise ShutdownError if @shutdown
30
+
31
+ begin
32
+ latest_msg ||= @client.incr('latest_added')
33
+ @client.add(latest_msg.to_s, msg)
34
+ @client.set("added_#{latest_msg}", true)
35
+ rescue Exception
36
+ warn "Error on add: #{$!.inspect}, retrying"
37
+ sleep 1
38
+ retry
39
+ end
40
+ end
41
+
42
+ # ! lost message potential !
43
+ # If we die between incr and state(:set) the message _will_ be
44
+ # lost. This would have to be due to hard process kill or other like events.
45
+ def get_msg
46
+ raise ShutdownError if @shutdown
47
+
48
+ if key = @first_key
49
+ @first_key = nil
50
+ else
51
+ key = @client.incr('latest_read').to_s
52
+ end
53
+
54
+ start_time = Time.now
55
+ loop do
56
+ begin
57
+ if msg = @client.get(key)
58
+ begin
59
+ @client.delete(key)
60
+ rescue Exception
61
+ warn "Error while deleting key #{$!.inspect}"
62
+ end
63
+ return msg
64
+ end
65
+ rescue Exception
66
+ warn "Error on get, #{$!.inspect}, retrying"
67
+ end
68
+ state(:set, key) unless @state_set
69
+ raise ShutdownError if @shutdown
70
+ return nil if (Time.now - start_time) > @add_timeout and failed_add?(key)
71
+ sleep 1
72
+ start_time = Time.now if msgs_left(true) < 0
73
+ end
74
+ ensure
75
+ state(:delete, key) if @state_set and ! @shutdown
76
+ end
77
+
78
+ def msgs_left(neg_value = false)
79
+ latest_added = @client.get('latest_added', true).to_i
80
+ latest_read = @client.get('latest_read', true).to_i
81
+
82
+ # check for 64bit boundary crossing
83
+ if latest_added > 2**63 and latest_read < 2**62
84
+ latest_read += 2**64
85
+ elsif latest_read > 2**63 and latest_added < 2**62
86
+ latest_added += 2**64
87
+ end
88
+
89
+ diff = latest_added - latest_read
90
+ neg_value ? diff : [0, diff].max
91
+ end
92
+
93
+ def shutdown
94
+ @shutdown = true
95
+ end
96
+
97
+ private
98
+
99
+ def failed_add?(key)
100
+ msgs_left(true) >= 0 and ! @client.get("added_#{key}")
101
+ end
102
+
103
+ def state(action, key = nil)
104
+ return @client.get("state_#@name") if action == :get
105
+ @client.send(action, "state_#@name", key)
106
+ @state_set = (action == :set)
107
+ rescue Exception
108
+ warn "Error on #{action} state, #{$!.inspect}, retrying"
109
+ sleep 1
110
+ retry
111
+ end
112
+ end
@@ -0,0 +1,15 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = "memcache_queue"
3
+ s.version = "0.0.1"
4
+ s.summary = "memcached based queue"
5
+ s.email = "coderrr.contact@gmail.com"
6
+ s.homepage = "http://github.com/coderrr/memcache_queue"
7
+ s.description = "simple message queue which requires only this client and a memcached server"
8
+ s.authors = ["coderrr"]
9
+ s.files = [
10
+ "README.markdown",
11
+ "memcache_queue.gemspec",
12
+ "lib/memcache_queue.rb"
13
+ ]
14
+ s.add_dependency("memcache-client", [">= 1.5.0"])
15
+ end
metadata ADDED
@@ -0,0 +1,64 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: coderrr-memcache_queue
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - coderrr
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-02-13 00:00:00 -08:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: memcache-client
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 1.5.0
24
+ version:
25
+ description: simple message queue which requires only this client and a memcached server
26
+ email: coderrr.contact@gmail.com
27
+ executables: []
28
+
29
+ extensions: []
30
+
31
+ extra_rdoc_files: []
32
+
33
+ files:
34
+ - README.markdown
35
+ - memcache_queue.gemspec
36
+ - lib/memcache_queue.rb
37
+ has_rdoc: false
38
+ homepage: http://github.com/coderrr/memcache_queue
39
+ post_install_message:
40
+ rdoc_options: []
41
+
42
+ require_paths:
43
+ - lib
44
+ required_ruby_version: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: "0"
49
+ version:
50
+ required_rubygems_version: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: "0"
55
+ version:
56
+ requirements: []
57
+
58
+ rubyforge_project:
59
+ rubygems_version: 1.2.0
60
+ signing_key:
61
+ specification_version: 2
62
+ summary: memcached based queue
63
+ test_files: []
64
+