em-pg-client-helper 0.5.0 → 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -10,10 +10,10 @@ class PG::EM::Client::Helper::DeferrableGroup
10
10
  # Create a new deferrable group.
11
11
  #
12
12
  def initialize
13
- @failed = false
14
- @finished = false
15
- @first_failure = nil
13
+ @closed = false
14
+ @failure = nil
16
15
  @outstanding = []
16
+
17
17
  yield(self) if block_given?
18
18
  end
19
19
 
@@ -24,19 +24,34 @@ class PG::EM::Client::Helper::DeferrableGroup
24
24
  # @return [EM::Deferrable] the same deferrable.
25
25
  #
26
26
  # @raise [RuntimeError] if you attempt to add a deferrable after the
27
- # group has already "completed" (that is, all deferrables that were
28
- # previously added to the group have finished).
27
+ # group has been closed (that is, the `#close` method has been called),
28
+ # indicating that the deferrable group doesn't have any more deferrables
29
+ # to add.
29
30
  #
30
31
  def add(df)
31
- if @finished
32
+ if @closed
32
33
  raise RuntimeError,
33
- "This deferrable group has already completed."
34
+ "This deferrable group is closed."
34
35
  end
35
36
 
36
37
  @outstanding << df
37
38
  df.callback { completed(df) }.errback { |ex| failed(df, ex) }
38
39
  end
39
40
 
41
+ # Tell the group that no further deferrables are to be added
42
+ #
43
+ # If all the deferrables in a group are complete, the group can't be sure
44
+ # whether further deferrables may be added in the future. By requiring
45
+ # an explicit `#close` call before the group completes, this ambiguity is
46
+ # avoided. It does, however, mean that if you forget to close the
47
+ # deferrable group, your code is going to hang. Such is the risk of
48
+ # async programming.
49
+ #
50
+ def close
51
+ @closed = true
52
+ maybe_done
53
+ end
54
+
40
55
  # Mark a deferrable as having been completed.
41
56
  #
42
57
  # If this is the last deferrable in the group, then the callback/errback
@@ -58,8 +73,7 @@ class PG::EM::Client::Helper::DeferrableGroup
58
73
  # will unfortunately be eaten by a grue.
59
74
  #
60
75
  def failed(df, ex)
61
- @first_failure ||= ex
62
- @failed = true
76
+ @failure ||= ex
63
77
  completed(df)
64
78
  end
65
79
 
@@ -67,10 +81,9 @@ class PG::EM::Client::Helper::DeferrableGroup
67
81
  # Called every time a deferrable finishes, just in case we're ready to
68
82
  # trigger our callbacks.
69
83
  def maybe_done
70
- if @outstanding.empty?
71
- @finished = true
72
- if @failed
73
- fail(@first_failure)
84
+ if @closed and @outstanding.empty?
85
+ if @failure
86
+ fail(@failure)
74
87
  else
75
88
  succeed
76
89
  end
@@ -7,12 +7,15 @@ class PG::EM::Client::Helper::Transaction
7
7
  def initialize(conn, opts, &blk)
8
8
  @conn = conn
9
9
  @opts = opts
10
- @active = true
10
+ # This can be `nil` if the txn is in progress, or it will be
11
+ # true or false to indicate success/failure of the txn
12
+ @committed = nil
11
13
 
12
14
  DeferrableGroup.new do |dg|
13
15
  @dg = dg
14
16
 
15
- conn.exec_defer("BEGIN").callback do
17
+ trace_query("BEGIN")
18
+ @conn.exec_defer("BEGIN").callback do
16
19
  begin
17
20
  blk.call(self)
18
21
  rescue StandardError => ex
@@ -20,9 +23,10 @@ class PG::EM::Client::Helper::Transaction
20
23
  end
21
24
  end.errback { |ex| rollback(ex) }.tap { |df| @dg.add(df) }
22
25
  end.callback do
23
- rollback(RuntimeError.new("txn.commit was not called")) if @active
26
+ rollback(RuntimeError.new("txn.commit was not called")) unless @committed
27
+ self.succeed
24
28
  end.errback do |ex|
25
- rollback(ex)
29
+ self.fail(ex)
26
30
  end
27
31
  end
28
32
 
@@ -33,11 +37,16 @@ class PG::EM::Client::Helper::Transaction
33
37
  # exception will be raised.
34
38
  #
35
39
  def commit
36
- if @active
37
- @conn.exec_defer("COMMIT").callback do
38
- @active = false
39
- self.succeed
40
- end.errback { |ex| rollback(ex) }.tap { |df| @dg.add(df) }
40
+ if @committed.nil?
41
+ trace_query("COMMIT")
42
+ @conn.exec_defer("COMMIT").tap do |df|
43
+ @dg.add(df)
44
+ end.callback do
45
+ @committed = true
46
+ @dg.close
47
+ end.errback do |ex|
48
+ rollback(ex)
49
+ end
41
50
  end
42
51
  end
43
52
 
@@ -47,11 +56,15 @@ class PG::EM::Client::Helper::Transaction
47
56
  # event of a database error or other exception.
48
57
  #
49
58
  def rollback(ex)
50
- if @active
51
- @conn.exec_defer("ROLLBACK") do
52
- @active = false
53
- self.fail(ex)
54
- end.tap { |df| @dg.add(df) }
59
+ if @committed.nil?
60
+ trace_query("ROLLBACK")
61
+ @conn.exec_defer("ROLLBACK").tap do |df|
62
+ @dg.add(df)
63
+ end.callback do
64
+ @committed = false
65
+ @dg.fail(ex)
66
+ @dg.close
67
+ end
55
68
  end
56
69
  end
57
70
 
@@ -74,15 +87,22 @@ class PG::EM::Client::Helper::Transaction
74
87
  # specific query finishes.
75
88
  #
76
89
  def exec(sql, values=[], &blk)
77
- unless @active
90
+ unless @committed.nil?
78
91
  raise RuntimeError,
79
92
  "Cannot execute a query in a transaction that has been closed"
80
93
  end
81
94
 
95
+ trace_query(sql, values)
82
96
  @conn.exec_defer(sql, values).tap do |df|
83
97
  @dg.add(df)
84
98
  df.callback(&blk) if blk
99
+ end.errback do |ex|
100
+ rollback(ex)
85
101
  end
86
102
  end
87
103
  alias_method :exec_defer, :exec
104
+
105
+ def trace_query(q, v=nil)
106
+ $stderr.puts "#{@conn.inspect}: #{q} #{v.inspect}" if ENV['EM_PG_TXN_TRACE']
107
+ end
88
108
  end
@@ -16,11 +16,6 @@ describe "PG::EM::Client::Helper#db_transaction" do
16
16
  and_return(df).
17
17
  ordered
18
18
 
19
- # Rollback expects a yield
20
- if q == "ROLLBACK"
21
- ex.and_yield()
22
- end
23
-
24
19
  EM.add_timer(exec_time) do
25
20
  df.__send__(disposition)
26
21
  end
@@ -32,7 +27,7 @@ describe "PG::EM::Client::Helper#db_transaction" do
32
27
 
33
28
  def in_em
34
29
  EM.run do
35
- EM.add_timer(1) { EM.stop; raise "test timeout" }
30
+ EM.add_timer(0.5) { EM.stop; raise "test timeout" }
36
31
  yield
37
32
  end
38
33
  end
@@ -41,8 +36,8 @@ describe "PG::EM::Client::Helper#db_transaction" do
41
36
  in_em do
42
37
  expect_query("BEGIN")
43
38
  expect_query("COMMIT")
44
- in_transaction do
45
- # Nothing
39
+ in_transaction do |txn|
40
+ txn.commit
46
41
  end
47
42
  end
48
43
  end
@@ -51,8 +46,8 @@ describe "PG::EM::Client::Helper#db_transaction" do
51
46
  in_em do
52
47
  expect_query_failure("BEGIN")
53
48
  expect_query("ROLLBACK")
54
- in_transaction do
55
- # Nothing
49
+ in_transaction do |txn|
50
+ txn.commit
56
51
  end
57
52
  end
58
53
  end
@@ -62,8 +57,8 @@ describe "PG::EM::Client::Helper#db_transaction" do
62
57
  expect_query("BEGIN")
63
58
  expect_query_failure("COMMIT")
64
59
  expect_query("ROLLBACK")
65
- in_transaction do
66
- # Nothing
60
+ in_transaction do |txn|
61
+ txn.commit
67
62
  end
68
63
  end
69
64
  end
@@ -74,7 +69,9 @@ describe "PG::EM::Client::Helper#db_transaction" do
74
69
  expect_query('INSERT INTO "foo" ("bar") VALUES ($1)', ["baz"])
75
70
  expect_query("COMMIT")
76
71
  in_transaction do |txn|
77
- txn.insert("foo", :bar => 'baz')
72
+ txn.insert("foo", :bar => 'baz') do
73
+ txn.commit
74
+ end
78
75
  end
79
76
  end
80
77
  end
@@ -85,7 +82,9 @@ describe "PG::EM::Client::Helper#db_transaction" do
85
82
  expect_query_failure('INSERT INTO "foo" ("bar") VALUES ($1)', ["baz"])
86
83
  expect_query("ROLLBACK")
87
84
  in_transaction do |txn|
88
- txn.insert("foo", :bar => 'baz')
85
+ txn.insert("foo", :bar => 'baz') do
86
+ txn.commit
87
+ end
89
88
  end
90
89
  end
91
90
  end
@@ -101,7 +100,9 @@ describe "PG::EM::Client::Helper#db_transaction" do
101
100
  in_transaction do |txn|
102
101
  txn.insert("foo", :bar => 'baz') do
103
102
  txn.insert("foo", :bar => 'wombat') do
104
- txn.insert("foo", :bar => 'quux')
103
+ txn.insert("foo", :bar => 'quux') do
104
+ txn.commit
105
+ end
105
106
  end
106
107
  end
107
108
  end
@@ -124,7 +125,9 @@ describe "PG::EM::Client::Helper#db_transaction" do
124
125
  in_transaction do |txn|
125
126
  txn.insert("foo", :bar => 'baz') do
126
127
  txn.insert("foo", :bar => 'wombat') do
127
- txn.insert("foo", :bar => 'quux')
128
+ txn.insert("foo", :bar => 'quux') do
129
+ txn.commit
130
+ end
128
131
  end
129
132
  end
130
133
  end
@@ -137,8 +140,9 @@ describe "PG::EM::Client::Helper#db_transaction" do
137
140
  expect_query('INSERT INTO "foo" ("bar") VALUES ($1)', ["baz"])
138
141
  expect_query("ROLLBACK")
139
142
  in_transaction do |txn|
140
- txn.insert("foo", :bar => 'baz')
141
- txn.rollback("Because I can")
143
+ txn.insert("foo", :bar => 'baz') do
144
+ txn.rollback("Because I can")
145
+ end
142
146
  end
143
147
  end
144
148
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: em-pg-client-helper
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.5.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -261,7 +261,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
261
261
  version: '0'
262
262
  segments:
263
263
  - 0
264
- hash: 472890837169152565
264
+ hash: -4325502789198036899
265
265
  required_rubygems_version: !ruby/object:Gem::Requirement
266
266
  none: false
267
267
  requirements:
@@ -270,7 +270,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
270
270
  version: '0'
271
271
  segments:
272
272
  - 0
273
- hash: 472890837169152565
273
+ hash: -4325502789198036899
274
274
  requirements: []
275
275
  rubyforge_project:
276
276
  rubygems_version: 1.8.23