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.



70
71
72
# File 'lib/webhookdb/idempotency.rb', line 70

def _every
  @_every
end

#_in_memoryObject

Returns the value of attribute _in_memory.



70
71
72
# File 'lib/webhookdb/idempotency.rb', line 70

def _in_memory
  @_in_memory
end

#_keyObject

Returns the value of attribute _key.



70
71
72
# File 'lib/webhookdb/idempotency.rb', line 70

def _key
  @_key
end

#_once_everObject

Returns the value of attribute _once_ever.



70
71
72
# File 'lib/webhookdb/idempotency.rb', line 70

def _once_ever
  @_once_ever
end

#_sepconnObject

Returns the value of attribute _sepconn.



70
71
72
# File 'lib/webhookdb/idempotency.rb', line 70

def _sepconn
  @_sepconn
end

#_storedObject

Returns the value of attribute _stored.



70
71
72
# File 'lib/webhookdb/idempotency.rb', line 70

def _stored
  @_stored
end

Instance Method Details

#_update_row(db, result) ⇒ Object



145
146
147
148
149
# File 'lib/webhookdb/idempotency.rb', line 145

def _update_row(db, result)
  jresult = self._stored ? result.as_json : result
  db.finish(self._key, last_run: Time.now, stored: self._stored, result: jresult)
  return jresult
end

#executeObject



113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# File 'lib/webhookdb/idempotency.rb', line 113

def execute(&)
  if self._in_memory
    db = InMemory.new(Webhookdb::Idempotency.memory_cache, Webhookdb::Idempotency._memory_cache_results)
  elsif self._sepconn
    db = InDatabase.new(Webhookdb::Idempotency.separate_connection)
  else
    conn = Webhookdb::Idempotency.db
    Webhookdb::Postgres.check_transaction(
      conn,
      "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.",
    )
    db = InDatabase.new(conn)
  end

  db.ensure(self._key)
  db.transaction do
    idem_row = db.lock(self._key)
    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

#in_memoryObject

If set, run a server-side idempotency (just for this process, across all threads) rather than in the database (for all processes). This is useful as a backoff mechanism for certain actions, like log sampling. Note, this uses an unbounded cache size for the sake of simplicity and performance, so be careful to use this with keys that will not grow infinitely.



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

def in_memory
  self._in_memory = true
  return self
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:



76
77
78
79
# File 'lib/webhookdb/idempotency.rb', line 76

def stored
  self._stored = true
  return self
end

#under_key(key, &block) ⇒ Builder

Returns:



107
108
109
110
111
# File 'lib/webhookdb/idempotency.rb', line 107

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:



101
102
103
104
# File 'lib/webhookdb/idempotency.rb', line 101

def using_seperate_connection
  self._sepconn = true
  return self
end