Class: Webhookdb::Idempotency::Builder

Inherits:
Object
  • Object
show all
Defined in:
lib/webhookdb/idempotency.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#_everyObject

Returns the value of attribute _every.



66
67
68
# File 'lib/webhookdb/idempotency.rb', line 66

def _every
  @_every
end

#_keyObject

Returns the value of attribute _key.



66
67
68
# File 'lib/webhookdb/idempotency.rb', line 66

def _key
  @_key
end

#_once_everObject

Returns the value of attribute _once_ever.



66
67
68
# File 'lib/webhookdb/idempotency.rb', line 66

def _once_ever
  @_once_ever
end

#_sepconnObject

Returns the value of attribute _sepconn.



66
67
68
# File 'lib/webhookdb/idempotency.rb', line 66

def _sepconn
  @_sepconn
end

#_storedObject

Returns the value of attribute _stored.



66
67
68
# File 'lib/webhookdb/idempotency.rb', line 66

def _stored
  @_stored
end

Instance Method Details

#_update_row(db, result) ⇒ Object



128
129
130
131
132
133
134
135
136
# File 'lib/webhookdb/idempotency.rb', line 128

def _update_row(db, result)
  updates = {last_run: Time.now}
  if self._stored
    result = result.as_json
    updates[:stored_result] = Sequel.pg_jsonb_wrap(result)
  end
  db[:idempotencies].where(key: self._key).update(updates)
  return result
end

#executeObject



99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/webhookdb/idempotency.rb', line 99

def execute
  if self._sepconn
    db = Webhookdb::Idempotency.separate_connection
  else
    db = Webhookdb::Idempotency.db
    Webhookdb::Postgres.check_transaction(
      db,
      "Cannot use idempotency while already in a transaction, since side effects may not be idempotent. " \
      "You can chain withusing_seperate_connection to run the idempotency itself separately.",
    )
  end

  db[:idempotencies].insert_conflict.insert(key: self._key)
  db.transaction do
    idem_row = db[:idempotencies].where(key: self._key).for_update.first
    if idem_row.fetch(:last_run).nil?
      result = yield()
      result = self._update_row(db, result)
      return result
    end
    noop_result = self._stored ? idem_row.fetch(:stored_result) : NOOP
    return noop_result if self._once_ever
    return noop_result if Time.now < (idem_row[:last_run] + self._every)
    result = yield()
    result = self._update_row(db, result)
    return result
  end
end

#storedBuilder

If set, the result of block is stored as JSON, and returned when an idempotent call is made. The JSON value (as_json) is returned from the block in all cases.

Returns:



72
73
74
75
# File 'lib/webhookdb/idempotency.rb', line 72

def stored
  self._stored = true
  return self
end

#under_key(key, &block) ⇒ Builder

Returns:



93
94
95
96
97
# File 'lib/webhookdb/idempotency.rb', line 93

def under_key(key, &block)
  self._key = key
  return self.execute(&block) if block
  return self
end

#using_seperate_connectionBuilder

Run the idempotency on a separate connection. Allows use of idempotency within an existing transaction block, which is normally not allowed. Usually should be used with #stored, since otherwise the result of the idempotency will be lost.

NOTE: When calling code with using_seperate_connection, you may want to use the spec metadata ‘truncate: Webhookdb::Idempotency` since the row won’t be covered by the spec’s transaction.

Returns:



87
88
89
90
# File 'lib/webhookdb/idempotency.rb', line 87

def using_seperate_connection
  self._sepconn = true
  return self
end