em-pg-client-helper 0.5.0 → 0.5.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.
@@ -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