pg_pipeline 0.3.3 → 0.3.4

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.
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "pg"
3
+ require 'pg'
4
4
 
5
- require_relative "session"
5
+ require_relative 'session'
6
6
 
7
7
  module PgPipeline
8
8
  class Transaction < Session
@@ -30,68 +30,67 @@ module PgPipeline
30
30
  module TransactionOps
31
31
  module_function
32
32
 
33
- def run(tx)
34
- SessionOps.ensure_active!(tx)
35
- raise Error, "transaction is already open" if tx.open?
33
+ def run(transaction)
34
+ SessionOps.ensure_active!(transaction)
35
+ raise Error, 'transaction is already open' if transaction.open?
36
36
 
37
- conn = SessionOps.connection(tx)
38
- conn.exec("BEGIN")
39
- tx.__send__(:open=, true)
37
+ conn = SessionOps.connection(transaction)
38
+ conn.exec('BEGIN')
39
+ transaction.__send__(:open=, true)
40
40
  begin
41
- result = yield tx
41
+ result = yield transaction
42
42
  commit(conn)
43
- tx.__send__(:open=, false)
43
+ transaction.__send__(:open=, false)
44
44
  result
45
45
  rescue Exception
46
- rollback_quietly(tx)
46
+ rollback_quietly(transaction)
47
47
  raise
48
48
  end
49
49
  end
50
50
 
51
51
  def commit(conn)
52
- conn.exec("COMMIT")
53
- rescue PG::Error => error
54
- raise unless indeterminate_commit_failure?(conn, error)
52
+ conn.exec('COMMIT')
53
+ rescue PG::Error => e
54
+ raise unless indeterminate_commit_failure?(conn, e)
55
55
 
56
56
  raise IndeterminateCommitError.new(
57
- "COMMIT acknowledgement was not received; the transaction may have committed " \
58
- "and must not be retried blindly (#{error.class}: #{error.message})"
59
- ), cause: error
57
+ 'COMMIT acknowledgement was not received; the transaction may have committed ' \
58
+ "and must not be retried blindly (#{e.class}: #{e.message})"
59
+ ), cause: e
60
60
  end
61
61
 
62
62
  def indeterminate_commit_failure?(conn, error)
63
63
  return true if defined?(PG::ConnectionBad) && error.is_a?(PG::ConnectionBad)
64
+ return false unless conn.respond_to?(:finished?) && conn.respond_to?(:status)
64
65
  return true if conn.finished?
65
66
 
66
67
  conn.status != PG::CONNECTION_OK
67
68
  rescue PG::Error
68
69
  true
69
- rescue NoMethodError
70
- false
71
70
  end
72
71
 
73
- def savepoint(tx, name)
74
- SessionOps.ensure_active!(tx)
75
- raise Error, "savepoint requires an open transaction" unless tx.open?
72
+ def savepoint(transaction, name)
73
+ SessionOps.ensure_active!(transaction)
74
+ raise Error, 'savepoint requires an open transaction' unless transaction.open?
76
75
 
77
- conn = SessionOps.connection(tx)
78
- seq = tx.__send__(:savepoint_seq) + 1
79
- tx.__send__(:savepoint_seq=, seq)
76
+ conn = SessionOps.connection(transaction)
77
+ seq = transaction.__send__(:savepoint_seq) + 1
78
+ transaction.__send__(:savepoint_seq=, seq)
80
79
  point = name || "pgp_sp_#{seq}"
81
80
  ident = conn.quote_ident(point)
82
81
  conn.exec("SAVEPOINT #{ident}")
83
82
  begin
84
- result = yield tx
83
+ result = yield transaction
85
84
  conn.exec("RELEASE SAVEPOINT #{ident}")
86
85
  result
87
86
  rescue Exception
88
- rollback_to_savepoint(tx, ident)
87
+ rollback_to_savepoint(transaction, ident)
89
88
  raise
90
89
  end
91
90
  end
92
91
 
93
- def rollback_to_savepoint(tx, ident)
94
- conn = SessionOps.connection(tx)
92
+ def rollback_to_savepoint(transaction, ident)
93
+ conn = SessionOps.connection(transaction)
95
94
  return unless conn
96
95
 
97
96
  conn.exec("ROLLBACK TO SAVEPOINT #{ident}")
@@ -100,15 +99,15 @@ module PgPipeline
100
99
  nil
101
100
  end
102
101
 
103
- def rollback_quietly(tx)
104
- return unless tx.open?
102
+ def rollback_quietly(transaction)
103
+ return unless transaction.open?
105
104
 
106
- conn = SessionOps.connection(tx)
107
- conn&.exec("ROLLBACK")
105
+ conn = SessionOps.connection(transaction)
106
+ conn&.exec('ROLLBACK')
108
107
  rescue PG::Error
109
108
  nil
110
109
  ensure
111
- tx.__send__(:open=, false)
110
+ transaction.__send__(:open=, false)
112
111
  end
113
112
  end
114
113
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "pg"
4
- require_relative "errors"
3
+ require 'pg'
4
+ require_relative 'errors'
5
5
 
6
6
  module PgPipeline
7
7
  class TypeMaps
@@ -40,47 +40,62 @@ module PgPipeline
40
40
  def ensure_bundle!(connection_args)
41
41
  return if @bundle && @bundle != :failed
42
42
 
43
- conn = nil
44
- conn = connection_args.nil? ? PG::Connection.new : PG::Connection.new(connection_args)
45
- @bundle = PG::BasicTypeRegistry::CoderMapsBundle.new(conn)
46
- @text_map_for_results = PG::BasicTypeMapForResults.new(@bundle)
43
+ build_bundle(connection_args)
47
44
  rescue StandardError => e
48
45
  @bundle = :failed
49
46
  @text_map_for_results = nil
50
47
  raise Error, "failed to build CoderMapsBundle (#{e.class}: #{e.message})"
48
+ end
49
+
50
+ private
51
+
52
+ def build_bundle(connection_args)
53
+ conn = open_connection(connection_args)
54
+ @bundle = PG::BasicTypeRegistry::CoderMapsBundle.new(conn)
55
+ @text_map_for_results = PG::BasicTypeMapForResults.new(@bundle)
51
56
  ensure
52
- begin
53
- conn&.close
54
- rescue StandardError
55
- nil
56
- end
57
+ close_connection(conn)
57
58
  end
58
59
 
60
+ def open_connection(connection_args)
61
+ return PG::Connection.new if connection_args.nil?
62
+
63
+ PG::Connection.new(connection_args)
64
+ end
65
+
66
+ def close_connection(conn)
67
+ conn&.close
68
+ rescue StandardError
69
+ nil
70
+ end
71
+
72
+ public
73
+
59
74
  def apply!(request, result, _conn)
60
75
  map = request.type_map
61
76
  return if map.nil?
62
77
 
63
- if map.equal?(PENDING)
64
- name = request.statement_name
65
- map = @cache[name]
66
- unless map
67
- map = build_column_map!(result)
68
- @cache[name] = map
69
- end
70
- request.type_map = map
71
- end
78
+ map = resolve_type_map(request, result, map)
79
+ request.type_map = map if request.type_map.equal?(PENDING)
72
80
 
73
81
  result.type_map = map
74
82
  end
75
83
 
76
84
  private
77
85
 
86
+ def resolve_type_map(request, result, map)
87
+ return map unless map.equal?(PENDING)
88
+
89
+ name = request.statement_name
90
+ @cache[name] ||= build_column_map!(result)
91
+ end
92
+
78
93
  def build_column_map!(result)
79
94
  unless result.result_status == PG::PGRES_TUPLES_OK && result.nfields.positive?
80
- raise Error, "typed mapping requires a TUPLES_OK result with at least one column"
95
+ raise Error, 'typed mapping requires a TUPLES_OK result with at least one column'
81
96
  end
82
97
  if @bundle == :failed || @text_map_for_results.nil?
83
- raise Error, "typed result mapping is unavailable (CoderMapsBundle failed)"
98
+ raise Error, 'typed result mapping is unavailable (CoderMapsBundle failed)'
84
99
  end
85
100
 
86
101
  @text_map_for_results.build_column_map(result)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module PgPipeline
4
- VERSION = "0.3.3"
4
+ VERSION = '0.3.4'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pg_pipeline
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.3
4
+ version: 0.3.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Roman Hajdarov