fairway 0.2.7 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,15 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 560fe83c9779d40b22fe2d5e093d3ad9310dd9ed
4
- data.tar.gz: f1c2d3c7933944f75a0df7c987430a5a524193bc
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ OGE1MjlkNzEzY2FiZDc0MWMzMGNkZDhlYjkxODg4MzY3ZmJhNGE0NA==
5
+ data.tar.gz: !binary |-
6
+ ZjBiMzdjNmQ3YWI4Mjg1OTE5MDVkNTU2OTUwMTZiNTIwODhjZDg5OQ==
5
7
  SHA512:
6
- metadata.gz: 3c20f8ce9420514cd5ca9c1b54382aa5a8ce0bdd9f7e9947981864edfb169c54d6557ee0eb6c0f323727406d059c9054885386e97d5199f45ded8d4bceaea58b
7
- data.tar.gz: fb5e08076353e022fd4fbc9207d79ea566b014c3e789b056a8107a3bdf0cf2615c5d366a5fd577b66c18b621ecbfa3bd387178f08b47483e5fe9619c5a17c9b2
8
+ metadata.gz: !binary |-
9
+ ODAyMTVhODhiZWRmY2NhMzgyYTkyMzliZDIyNDUyOGM2NGJkMWY3Nzg1MmVm
10
+ NmZhM2Q5OWI4NWZkNGQzZWIxOWQyMGJmZGM2NWUxOTY5ZjI0MmUzNmZiMTcx
11
+ MTkwYzlhYzJkNWQyMzVmMjdhYThhNzAzMzI2YzMxNmFiZWY2Y2Y=
12
+ data.tar.gz: !binary |-
13
+ YWRjM2RhYWI3NzJjNDljZmQwYjgxYzIzZGMwNGI4MDliZmY2NTFkZGY0ZDlm
14
+ Y2U3MGU0YTUyZjU4ODNhNzA3N2RkOTI4ODYwYWY2NDM1YzYzMDk4NzQ5NDM1
15
+ MjRiZGM1MjdkYjU1N2M1NTI0YjgzYjYwMGE0MzJlNjA5NjExMjA=
data/Gemfile.lock CHANGED
@@ -1,8 +1,8 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- fairway (0.2.6)
5
- activesupport
4
+ fairway (0.2.7)
5
+ activesupport (= 4.0.2)
6
6
  connection_pool
7
7
  redis
8
8
  redis-namespace (>= 1.3.0)
@@ -16,14 +16,13 @@ GEM
16
16
  multi_json (~> 1.3)
17
17
  thread_safe (~> 0.1)
18
18
  tzinfo (~> 0.3.37)
19
- atomic (1.1.14)
20
19
  celluloid (0.12.4)
21
20
  facter (>= 1.6.12)
22
21
  timers (>= 1.0.0)
23
22
  connection_pool (1.0.0)
24
23
  diff-lcs (1.1.3)
25
24
  facter (1.6.17)
26
- i18n (0.6.9)
25
+ i18n (0.7.0)
27
26
  minitest (4.7.5)
28
27
  multi_json (1.5.0)
29
28
  rake (10.1.0)
@@ -44,10 +43,9 @@ GEM
44
43
  multi_json (~> 1)
45
44
  redis (~> 3)
46
45
  redis-namespace
47
- thread_safe (0.1.3)
48
- atomic
46
+ thread_safe (0.3.5)
49
47
  timers (1.1.0)
50
- tzinfo (0.3.38)
48
+ tzinfo (0.3.46)
51
49
 
52
50
  PLATFORMS
53
51
  ruby
@@ -57,3 +55,6 @@ DEPENDENCIES
57
55
  rake
58
56
  rspec
59
57
  sidekiq
58
+
59
+ BUNDLED WITH
60
+ 1.10.6
@@ -2,6 +2,7 @@ package fairway
2
2
 
3
3
  import (
4
4
  "fmt"
5
+
5
6
  "github.com/customerio/gospec"
6
7
  . "github.com/customerio/gospec"
7
8
  "github.com/customerio/redigo/redis"
@@ -37,4 +38,25 @@ func ChanneledConnectionSpec(c gospec.Context) {
37
38
  c.Expect(count, Equals, 0)
38
39
  })
39
40
  })
41
+
42
+ c.Specify("DeliverBytes", func() {
43
+ c.Specify("only queues up message for matching queues", func() {
44
+ r := config.Pool.Get()
45
+ defer r.Close()
46
+
47
+ count, _ := redis.Int(r.Do("llen", "fairway:myqueue:default"))
48
+ c.Expect(count, Equals, 0)
49
+ count, _ = redis.Int(r.Do("llen", "fairway:myqueue2:default"))
50
+ c.Expect(count, Equals, 0)
51
+
52
+ msg, _ := NewMsg(map[string]string{"type": "a"})
53
+
54
+ conn.DeliverBytes("channel:typea:channel", "default", []byte(msg.json()))
55
+
56
+ count, _ = redis.Int(r.Do("llen", "fairway:myqueue:default"))
57
+ c.Expect(count, Equals, 1)
58
+ count, _ = redis.Int(r.Do("llen", "fairway:myqueue2:default"))
59
+ c.Expect(count, Equals, 0)
60
+ })
61
+ })
40
62
  }
data/go/config.go CHANGED
@@ -32,7 +32,7 @@ func NewConfig(server string, db string, poolSize int) *Config {
32
32
  []*QueueDefinition{},
33
33
  &redis.Pool{
34
34
  MaxIdle: poolSize,
35
- MaxActive: poolSize,
35
+ MaxActive: 0,
36
36
  IdleTimeout: 240 * time.Second,
37
37
  Dial: func() (redis.Conn, error) {
38
38
  c, err := redis.Dial("tcp", server)
data/go/config_test.go CHANGED
@@ -25,10 +25,10 @@ func ConfigSpec(c gospec.Context) {
25
25
 
26
26
  c.Specify("sets redis pool size", func() {
27
27
  c.Expect(config.Pool.MaxIdle, Equals, 10)
28
- c.Expect(config.Pool.MaxActive, Equals, 10)
28
+ c.Expect(config.Pool.MaxActive, Equals, 0)
29
29
  config = NewConfig("localhost:6379", "15", 20)
30
30
  c.Expect(config.Pool.MaxIdle, Equals, 20)
31
- c.Expect(config.Pool.MaxActive, Equals, 20)
31
+ c.Expect(config.Pool.MaxActive, Equals, 0)
32
32
  })
33
33
 
34
34
  c.Specify("can specify custom namespace", func() {
data/go/connection.go CHANGED
@@ -5,6 +5,7 @@ type Connection interface {
5
5
  Queues() []*Queue
6
6
  Channel(*Msg) string
7
7
  Deliver(*Msg) error
8
+ DeliverBytes(channel, facet string, bytes []byte) error
8
9
  Configuration() *Config
9
10
  }
10
11
 
@@ -40,6 +41,10 @@ func (c *conn) Deliver(msg *Msg) error {
40
41
  return c.scripts.deliver(channel, facet, msg)
41
42
  }
42
43
 
44
+ func (c *conn) DeliverBytes(channel, facet string, msg []byte) error {
45
+ return c.scripts.deliverBytes(channel, facet, msg)
46
+ }
47
+
43
48
  func (c *conn) Configuration() *Config {
44
49
  return c.config
45
50
  }
@@ -97,6 +97,7 @@ func ConnectionSpec(c gospec.Context) {
97
97
  defer r.Close()
98
98
 
99
99
  r.Do("sadd", "fairway:myqueue:active_facets", "default")
100
+ r.Do("hset", "fairway:myqueue:facet_pool", "default", "1")
100
101
 
101
102
  msg, _ := NewMsg(map[string]string{})
102
103
 
data/go/fairway_ack.go ADDED
@@ -0,0 +1,60 @@
1
+ package fairway
2
+
3
+ func FairwayAck() string {
4
+ return `
5
+ local namespace = KEYS[1];
6
+
7
+ local k = function (queue, subkey)
8
+ return namespace .. queue .. ':' .. subkey;
9
+ end
10
+
11
+ local queue = ARGV[1];
12
+ local facet = ARGV[2];
13
+ local message = ARGV[3];
14
+
15
+ local active_facets = k(queue, 'active_facets');
16
+ local round_robin = k(queue, 'facet_queue');
17
+ local facet_pool = k(queue, 'facet_pool');
18
+ local inflight = k(queue, 'inflight');
19
+ local messages = k(queue, facet);
20
+ local inflight_total = k(queue, facet .. ':inflight');
21
+ local inflight_limit = k(queue, 'limit');
22
+ local priorities = k(queue, 'priorities');
23
+
24
+ local removed = tonumber(redis.call('zrem', inflight, message))
25
+
26
+ if removed > 0 then
27
+ -- Manage facet queue and active facets
28
+ local current = tonumber(redis.call('hget', facet_pool, facet)) or 0;
29
+ local priority = tonumber(redis.call('hget', priorities, facet)) or 1;
30
+ local length = redis.call('llen', messages);
31
+ local inflight_cur = tonumber(redis.call('decr', inflight_total)) or 0;
32
+ local inflight_max = tonumber(redis.call('get', inflight_limit)) or 0;
33
+
34
+ local n = 0
35
+
36
+ -- redis.log(redis.LOG_WARNING, current.."/"..length.."/"..priority.."/"..inflight_max.."/"..inflight_cur)
37
+
38
+ if inflight_max > 0 then
39
+ n = math.min(length, priority, inflight_max - inflight_cur);
40
+ else
41
+ n = math.min(length, priority);
42
+ end
43
+
44
+ -- redis.log(redis.LOG_WARNING, "ACK: "..current.."/"..n);
45
+
46
+ if n > current then
47
+ -- redis.log(redis.LOG_WARNING, "growing");
48
+ redis.call('lpush', round_robin, facet);
49
+ redis.call('hset', facet_pool, facet, current + 1);
50
+ end
51
+
52
+ if (current == 0 and length == 0 and inflight_cur == 0 and n == 0) then
53
+ redis.call('del', inflight_total);
54
+ redis.call('srem', active_facets, facet);
55
+ end
56
+ end
57
+
58
+ return removed
59
+ `
60
+ }
@@ -1,7 +1,7 @@
1
1
  package fairway
2
2
 
3
3
  func FairwayDeliver() string {
4
- return `
4
+ return `
5
5
  local namespace = KEYS[1];
6
6
  local topic = ARGV[1];
7
7
  local facet = ARGV[2];
@@ -23,45 +23,50 @@ for i = 1, #registered_queues, 2 do
23
23
  -- If the message topic matches the queue topic,
24
24
  -- we deliver the message to the queue.
25
25
  if string.find(topic, queue_topic) then
26
- local priorities = k(queue, 'priorities');
27
- local active_facets = k(queue, 'active_facets');
28
- local round_robin = k(queue, 'facet_queue');
29
- local facet_pool = k(queue, 'facet_pool');
26
+ local priorities = k(queue, 'priorities');
27
+ local active_facets = k(queue, 'active_facets');
28
+ local round_robin = k(queue, 'facet_queue');
29
+ local facet_pool = k(queue, 'facet_pool');
30
+ local inflight_total = k(queue, facet .. ':inflight');
31
+ local inflight_limit = k(queue, 'limit');
30
32
 
31
33
  -- Delivering the message to a queue is as simple as
32
34
  -- pushing it onto the facet's message list, and
33
35
  -- incrementing the length of the queue itself.
34
- redis.call('lpush', k(queue, facet), message)
36
+ local length = redis.call('lpush', k(queue, facet), message)
35
37
  redis.call('incr', k(queue, 'length'));
36
38
 
37
- -- If the facet just became active, we need to add
38
- -- the facet to the round-robin queue, so it's
39
- -- messages will be processed.
40
- if redis.call('sadd', active_facets, facet) == 1 then
41
- local priority = tonumber(redis.call('hget', priorities, facet)) or 1
42
39
 
43
- -- If the facet currently has a priority
44
- -- we need to jump start the facet by adding
45
- -- it to the round-robin queue and updating
46
- -- the current priority.
47
- if priority > 0 then
48
- redis.call('lpush', round_robin, facet);
49
- redis.call('hset', facet_pool, facet, 1);
50
-
51
- -- If the facet has no set priority, just set the
52
- -- current priority to zero. Since the facet just
53
- -- became active, we can be sure it's already zero
54
- -- or undefined.
55
- else
56
- redis.call('hset', facet_pool, facet, 0);
57
- end
40
+ -- Manage facet queue and active facets
41
+ local current = tonumber(redis.call('hget', facet_pool, facet)) or 0;
42
+ local priority = tonumber(redis.call('hget', priorities, facet)) or 1;
43
+ local inflight_cur = tonumber(redis.call('get', inflight_total)) or 0;
44
+ local inflight_max = tonumber(redis.call('get', inflight_limit)) or 0;
45
+
46
+ local n = 0
47
+
48
+ -- redis.log(redis.LOG_WARNING, current.."/"..length.."/"..priority.."/"..inflight_max.."/"..inflight_cur);
49
+
50
+ if inflight_max > 0 then
51
+ n = math.min(length, priority, inflight_max - inflight_cur);
52
+ else
53
+ n = math.min(length, priority);
54
+ end
55
+
56
+ -- redis.log(redis.LOG_WARNING, "PUSH: "..current.."/"..n);
57
+
58
+ if n > current then
59
+ -- redis.log(redis.LOG_WARNING, "growing");
60
+ redis.call('lpush', round_robin, facet);
61
+ redis.call('hset', facet_pool, facet, current + 1);
58
62
  end
63
+
64
+ redis.call('sadd', active_facets, facet)
59
65
  end
60
66
  end
61
67
 
62
68
  -- For any clients listening over pub/sub,
63
69
  -- we should publish the message.
64
70
  redis.call('publish', namespace .. topic, message);
65
-
66
71
  `
67
72
  }
@@ -1,7 +1,7 @@
1
1
  package fairway
2
2
 
3
3
  func FairwayDestroy() string {
4
- return `
4
+ return `
5
5
  local namespace = KEYS[1];
6
6
 
7
7
  local k = function (queue, subkey)
@@ -13,15 +13,18 @@ end
13
13
  -- provided queues, and delete related keys
14
14
  -- for each queue.
15
15
  for i, queue in ipairs(ARGV) do
16
- local priorities = k(queue, 'priorities');
17
- local active_facets = k(queue, 'active_facets');
18
- local round_robin = k(queue, 'facet_queue');
19
- local facet_pool = k(queue, 'facet_pool');
20
- local length = k(queue, 'length');
16
+ local priorities = k(queue, 'priorities');
17
+ local active_facets = k(queue, 'active_facets');
18
+ local round_robin = k(queue, 'facet_queue');
19
+ local facet_pool = k(queue, 'facet_pool');
20
+ local inflight = k(queue, 'inflight');
21
+ local inflight_limit = k(queue, 'limit');
22
+ local length = k(queue, 'length');
21
23
 
22
24
  local facets = redis.call('smembers', active_facets);
23
25
 
24
26
  for i = 1, #facets, 1 do
27
+ redis.call('del', k(queue, facets[i] .. ':inflight'));
25
28
  redis.call('del', k(queue, facets[i]));
26
29
  end
27
30
 
@@ -29,6 +32,8 @@ for i, queue in ipairs(ARGV) do
29
32
  redis.call('del', active_facets);
30
33
  redis.call('del', round_robin);
31
34
  redis.call('del', facet_pool);
35
+ redis.call('del', inflight);
36
+ redis.call('del', inflight_limit);
32
37
  redis.call('del', length);
33
38
  end
34
39
 
@@ -0,0 +1,15 @@
1
+ package fairway
2
+
3
+ func FairwayInflight() string {
4
+ return `
5
+ local namespace = KEYS[1];
6
+
7
+ local k = function (queue, subkey)
8
+ return namespace .. queue .. ':' .. subkey;
9
+ end
10
+
11
+ for i, queue in ipairs(ARGV) do
12
+ return redis.call('zrange', k(queue, 'inflight'), 0, -1);
13
+ end
14
+ `
15
+ }
data/go/fairway_peek.go CHANGED
@@ -1,11 +1,10 @@
1
1
  package fairway
2
2
 
3
3
  func FairwayPeek() string {
4
- return `
4
+ return `
5
5
  local namespace = KEYS[1];
6
6
 
7
7
  for index, queue_name in ipairs(ARGV) do
8
- local active_facets = namespace .. queue_name .. ':active_facets';
9
8
  local facet_queue = namespace .. queue_name .. ':facet_queue';
10
9
 
11
10
  local facet = redis.call('lrange', facet_queue, -1, -1)[1];
@@ -17,6 +16,5 @@ for index, queue_name in ipairs(ARGV) do
17
16
  return {queue_name, message};
18
17
  end
19
18
  end
20
-
21
19
  `
22
20
  }
@@ -0,0 +1,20 @@
1
+ package fairway
2
+
3
+ func FairwayPing() string {
4
+ return `
5
+ local namespace = KEYS[1];
6
+ local timestamp = tonumber(KEYS[2]);
7
+ local wait = tonumber(KEYS[3]);
8
+
9
+ local k = function (queue, subkey)
10
+ return namespace .. queue .. ':' .. subkey;
11
+ end
12
+
13
+ local queue = ARGV[1];
14
+ local message = ARGV[2];
15
+
16
+ local inflight = k(queue, 'inflight');
17
+
18
+ redis.call('zadd', inflight, timestamp + wait, message);
19
+ `
20
+ }
@@ -1,7 +1,7 @@
1
1
  package fairway
2
2
 
3
3
  func FairwayPriority() string {
4
- return `
4
+ return `
5
5
  local namespace = KEYS[1];
6
6
  local queue = ARGV[1];
7
7
  local facet = ARGV[2];
@@ -17,7 +17,7 @@ local facet_pool = k(queue, 'facet_pool');
17
17
 
18
18
  -- Find the current state of the facet for the queue
19
19
  local priority = tonumber(redis.call('hget', priorities, facet)) or 1;
20
- local current = tonumber(redis.call('hget', facet_pool, facet));
20
+ local current = tonumber(redis.call('hget', facet_pool, facet)) or 0;
21
21
 
22
22
  -- If priority is currently zero, we need to jump
23
23
  -- start the facet by adding it to the round-robin
@@ -31,6 +31,5 @@ end
31
31
  -- set the new priority, and the real priority
32
32
  -- will update lazily on pull.
33
33
  redis.call('hset', priorities, facet, new_priority);
34
-
35
34
  `
36
35
  }
data/go/fairway_pull.go CHANGED
@@ -1,8 +1,10 @@
1
1
  package fairway
2
2
 
3
3
  func FairwayPull() string {
4
- return `
4
+ return `
5
5
  local namespace = KEYS[1];
6
+ local timestamp = tonumber(KEYS[2]);
7
+ local wait = tonumber(KEYS[3]);
6
8
 
7
9
  local k = function (queue, subkey)
8
10
  return namespace .. queue .. ':' .. subkey;
@@ -13,10 +15,28 @@ end
13
15
  -- provided queues, and return a message
14
16
  -- from the first one that isn't empty.
15
17
  for i, queue in ipairs(ARGV) do
16
- local priorities = k(queue, 'priorities');
17
- local active_facets = k(queue, 'active_facets');
18
- local round_robin = k(queue, 'facet_queue');
19
- local facet_pool = k(queue, 'facet_pool');
18
+ local active_facets = k(queue, 'active_facets');
19
+ local round_robin = k(queue, 'facet_queue');
20
+ local inflight = k(queue, 'inflight');
21
+ local inflight_limit = k(queue, 'limit');
22
+ local priorities = k(queue, 'priorities');
23
+ local facet_pool = k(queue, 'facet_pool');
24
+
25
+ if wait ~= -1 then
26
+ -- Check if any current inflight messages
27
+ -- have been inflight for a long time.
28
+ local inflightmessage = redis.call('zrange', inflight, 0, 0, 'WITHSCORES');
29
+
30
+ -- If we have an inflight message and it's score
31
+ -- is less than the current pull timestamp, reset
32
+ -- the inflight score for the the message and resend.
33
+ if #inflightmessage > 0 then
34
+ if tonumber(inflightmessage[2]) <= timestamp then
35
+ redis.call('zadd', inflight, timestamp + wait, inflightmessage[1]);
36
+ return {queue, inflightmessage[1]}
37
+ end
38
+ end
39
+ end
20
40
 
21
41
  -- Pull a facet from the round-robin list.
22
42
  -- This list guarantees each active facet will have a
@@ -27,73 +47,59 @@ for i, queue in ipairs(ARGV) do
27
47
  -- If we found an active facet, we know the facet
28
48
  -- has at least one message available to be pulled
29
49
  -- from it's message queue.
30
- local messages = k(queue, facet);
31
- local message = redis.call('rpop', messages);
50
+ local messages = k(queue, facet);
51
+ local inflight_total = k(queue, facet .. ':inflight');
52
+
53
+ local message = redis.call('rpop', messages);
32
54
 
33
55
  if message then
56
+ if wait ~= -1 then
57
+ redis.call('zadd', inflight, timestamp + wait, message);
58
+ redis.call('incr', inflight_total);
59
+ end
60
+
34
61
  redis.call('decr', k(queue, 'length'));
35
62
  end
36
63
 
37
- local length = redis.call('llen', messages);
64
+ -- Manage facet queue and active facets
65
+ local current = tonumber(redis.call('hget', facet_pool, facet)) or 0;
66
+ local priority = tonumber(redis.call('hget', priorities, facet)) or 1;
67
+ local length = redis.call('llen', messages);
68
+ local inflight_cur = tonumber(redis.call('get', inflight_total)) or 0;
69
+ local inflight_max = tonumber(redis.call('get', inflight_limit)) or 0;
38
70
 
39
- -- If the length of the facet's message queue
40
- -- is empty, then it is no longer active as
41
- -- it no longer has any messages.
42
- if length == 0 then
43
- -- We remove the facet from the set of active
44
- -- facets and don't push the facet back on the
45
- -- round-robin queue.
46
- redis.call('srem', active_facets, facet);
47
-
48
- -- If the facet still has messages to process,
49
- -- it remains in the active facet set, and is
50
- -- pushed back on the round-robin queue.
51
- --
52
- -- Additionally, the priority of the facet may
53
- -- have changed, so we'll check and update the
54
- -- current facet's priority if needed.
71
+ local n = 0
72
+
73
+ -- redis.log(redis.LOG_WARNING, current.."/"..length.."/"..priority.."/"..inflight_max.."/"..inflight_cur);
74
+
75
+ if inflight_max > 0 then
76
+ n = math.min(length, priority, inflight_max - inflight_cur);
55
77
  else
56
- local priority = tonumber(redis.call('hget', priorities, facet)) or 1
57
- local current = tonumber(redis.call('hget', facet_pool, facet)) or 1
58
-
59
- -- If the current priority is less than the
60
- -- desired priority, let's increase the priority
61
- -- by pushing the current facet on the round-robin
62
- -- queue twice, and incrementing the current
63
- -- priority.
64
- --
65
- -- Note: If there aren't enough messages left
66
- -- on the facet, we don't increase priority.
67
- if current < priority and length > current then
68
- redis.call('lpush', round_robin, facet);
69
- redis.call('lpush', round_robin, facet);
70
- redis.call('hset', facet_pool, facet, current + 1);
71
-
72
- -- If the current priority is greater than the
73
- -- desired priority, let's decrease the priority
74
- -- by not pushing the current facet on the round-robin
75
- -- queue, and decrementing the current priority.
76
- --
77
- -- Note: Also decrement priority if there aren't
78
- -- enough messages for the current priority. This
79
- -- ensures priority (entries in the round-robin queue)
80
- -- never exceeds the number of messages for a given
81
- -- facet.
82
- elseif current > priority or current > length then
83
- redis.call('hset', facet_pool, facet, current - 1);
84
-
85
- -- If the current priority is equals the
86
- -- desired priority, let's maintain the current priority
87
- -- by pushing the current facet on the round-robin
88
- -- queue once.
89
- else
90
- redis.call('lpush', round_robin, facet);
91
- end
78
+ n = math.min(length, priority);
79
+ end
80
+
81
+ -- redis.log(redis.LOG_WARNING, "PULL: "..current.."/"..n);
82
+
83
+ if n < current then
84
+ -- redis.log(redis.LOG_WARNING, "shrinking");
85
+ redis.call('hset', facet_pool, facet, current - 1);
86
+ elseif n > current then
87
+ -- redis.log(redis.LOG_WARNING, "growing");
88
+ redis.call('lpush', round_robin, facet);
89
+ redis.call('lpush', round_robin, facet);
90
+ redis.call('hset', facet_pool, facet, current + 1);
91
+ else
92
+ -- redis.log(redis.LOG_WARNING, "maintaining");
93
+ redis.call('lpush', round_robin, facet);
94
+ end
95
+
96
+ if (current == 1 and length == 0 and inflight_cur == 0 and n == 0) then
97
+ redis.call('del', inflight_total);
98
+ redis.call('srem', active_facets, facet);
92
99
  end
93
100
 
94
101
  return {queue, message};
95
102
  end
96
103
  end
97
-
98
104
  `
99
105
  }
data/go/message.go CHANGED
@@ -6,6 +6,7 @@ import (
6
6
  )
7
7
 
8
8
  type Msg struct {
9
+ Original string
9
10
  *simplejson.Json
10
11
  }
11
12
 
@@ -20,7 +21,7 @@ func NewMsg(body interface{}) (*Msg, error) {
20
21
  return nil, err
21
22
  }
22
23
 
23
- return &Msg{simplej}, nil
24
+ return &Msg{string(bytes), simplej}, nil
24
25
  }
25
26
 
26
27
  func NewMsgFromString(body string) (*Msg, error) {
@@ -29,7 +30,7 @@ func NewMsgFromString(body string) (*Msg, error) {
29
30
  return nil, err
30
31
  }
31
32
 
32
- return &Msg{simplej}, nil
33
+ return &Msg{body, simplej}, nil
33
34
  }
34
35
 
35
36
  func (m *Msg) json() string {
data/go/queue.go CHANGED
@@ -9,6 +9,35 @@ func NewQueue(conn Connection, name string) *Queue {
9
9
  return &Queue{conn, name}
10
10
  }
11
11
 
12
- func (q *Queue) Pull() (string, *Msg) {
13
- return q.conn.Configuration().scripts().pull(q.name)
12
+ func (q *Queue) Name() string {
13
+ return q.name
14
+ }
15
+
16
+ func (q *Queue) Length() (int, error) {
17
+ return q.conn.Configuration().scripts().length(q.name)
18
+ }
19
+
20
+ func (q *Queue) Pull(resendTimeframe int) (string, *Msg) {
21
+ return q.conn.Configuration().scripts().pull(q.name, resendTimeframe)
22
+ }
23
+
24
+ func (q *Queue) Inflight() []string {
25
+ return q.conn.Configuration().scripts().inflight(q.name)
26
+ }
27
+
28
+ func (q *Queue) InflightLimit() (int, error) {
29
+ return q.conn.Configuration().scripts().inflightLimit(q.name)
30
+ }
31
+
32
+ func (q *Queue) SetInflightLimit(limit int) error {
33
+ return q.conn.Configuration().scripts().setInflightLimit(q.name, limit)
34
+ }
35
+
36
+ func (q *Queue) Ping(message *Msg, resendTimeframe int) error {
37
+ return q.conn.Configuration().scripts().ping(q.name, message, resendTimeframe)
38
+ }
39
+
40
+ func (q *Queue) Ack(message *Msg) error {
41
+ facet := q.conn.Configuration().Facet(message)
42
+ return q.conn.Configuration().scripts().ack(q.name, facet, message)
14
43
  }