lib/dynamoid/adapter_plugin/aws_sdk_v3/middleware/limit.rb
# frozen_string_literal: true
module Dynamoid
# @private
module AdapterPlugin
class AwsSdkV3
module Middleware
class Limit
def initialize(next_chain, record_limit: nil, scan_limit: nil)
@next_chain = next_chain
@record_limit = record_limit
@scan_limit = scan_limit
@record_count = 0
@scan_count = 0
end
def call(request)
# Adjust the limit down if the remaining record and/or scan limit are
# lower to obey limits. We can assume the difference won't be
# negative due to break statements below but choose smaller limit
# which is why we have 2 separate if statements.
#
# NOTE: Adjusting based on record_limit can cause many HTTP requests
# being made. We may want to change this behavior, but it affects
# filtering on data with potentially large gaps.
#
# Example:
# User.where('created_at.gte' => 1.day.ago).record_limit(1000)
# Records 1-999 User's that fit criteria
# Records 1000-2000 Users's that do not fit criteria
# Record 2001 fits criteria
#
# The underlying implementation will have 1 page for records 1-999
# then will request with limit 1 for records 1000-2000 (making 1000
# requests of limit 1) until hit record 2001.
if request[:limit] && @record_limit && @record_limit - @record_count < request[:limit]
request[:limit] = @record_limit - @record_count
end
if request[:limit] && @scan_limit && @scan_limit - @scan_count < request[:limit]
request[:limit] = @scan_limit - @scan_count
end
response = @next_chain.call(request)
@record_count += response.count
throw :stop_pagination if @record_limit && @record_count >= @record_limit
@scan_count += response.scanned_count
throw :stop_pagination if @scan_limit && @scan_count >= @scan_limit
response
end
end
end
end
end
end