Skip to content

v2.8.0

Latest
Compare
Choose a tag to compare
@mensfeld mensfeld released this 16 Sep 08:43
· 4 commits to master since this release
efa5dfe

This release contains BREAKING changes. Make sure to read and apply upgrade notes.

  • [Breaking] Require Ruby 3.1+.
  • [Breaking] Remove ability to abort transactions using throw(:abort). Please use raise WaterDrop::Errors::AbortTransaction.
  • [Breaking] Disallow (similar to ActiveRecord) exiting transactions with return, break or throw.
  • [Breaking] License changed from MIT to LGPL with an additional commercial option. Note: there is no commercial code in this repository. The commercial license is available for companies unable to use LGPL-licensed software for legal reasons.
  • [Enhancement] Make variants fiber safe.
  • [Enhancement] In transactional mode do not return any dispatched messages as none will be dispatched due to rollback.
  • [Enhancement] Align the LoggerListener async messages to reflect, that messages are delegated to the internal queue and not dispatched.
  • [Fix] Ensure, that :dispatched key for #produce_many_sync always contains delivery handles (final) and not delivery reports.

Upgrade Notes

PLEASE MAKE SURE TO READ AND APPLY THEM!

throw(:abort) No Longer Allowed To Abort Transactions

Replace:

producer.transaction do
  messages.each do |message|
    # Pipe all events
    producer.produce_async(topic: 'events', payload: message.raw_payload)
  end

  # And abort if more events are no longer needed
  throw(:abort) if KnowledgeBase.more_events_needed?
end

With:

producer.transaction do
  messages.each do |message|
    # Pipe all events
    producer.produce_async(topic: 'events', payload: message.raw_payload)
  end

  # And abort if more events are no longer needed
  raise(WaterDrop::AbortTransaction) if KnowledgeBase.more_events_needed?
end

return, break and throw No Longer Allowed Inside Transaction Block

Previously, transactions would abort if you exited early using return, break, or throw. This could create unexpected behavior, where users might not notice the rollback or have different intentions. For example, the following would trigger a rollback:

MAX = 10

def process(messages)
  count = 0

  producer.transaction do
    messages.each do |message|
      count += 1

      producer.produce_async(topic: 'events', payload: message.raw_payload)

      # This would trigger a rollback.
      return if count >= MAX
    end
  end
end

This is a source of errors, hence such exits are no longer allowed. You can implement similar flow control inside of your methods that are wrapped in a WaterDrop transaction:

MAX = 10

def process(messages)
  producer.transaction do
    # Early return from this method will not affect the transaction.
    # It will be committed
    insert_with_limit(messages)
  end
end

def insert_with_limit(messages)
  count = 0

  messages.each do |message|
    count += 1

    producer.produce_async(topic: 'events', payload: message.raw_payload)

    # This would trigger a rollback.
    return if count >= MAX
  end
end