docs: def _filter(self, environ, params):
          """
          Performs final filtering of the request to determine if this
          limit applies.  Returns False if the limit does not apply or
          if the call should not be limited, or True to apply the limit.
          """
  
          # Search for required query arguments
          if self.queries:
              # No query string available
              if 'QUERY_STRING' not in environ:
                  return False
  
              # Extract the list of provided query arguments from the
              # QUERY_STRING
              available = set(qstr.partition('=')[0] for qstr in
                              environ['QUERY_STRING'].split('&'))
  
              # Check if we have the required query arguments
              required = set(self.queries)
              if not required.issubset(available):
                  return False
  
          # Use only the parameters listed in use; we'll add the others
          # back later
          unused = {}
          for key, value in params.items():
              if key not in self.use:
                  unused[key] = value
  
          # Do this in a separate step so we avoid changing a
          # dictionary during traversal
          for key in unused:
              del params[key]
  
          # First, we need to set up any additional params required to
          # get the bucket.  If the DeferLimit exception is thrown, no
          # further processing is performed.
          try:
              additional = self.filter(environ, params, unused) or {}
          except DeferLimit:
              return False
  
          # Compute the bucket key
          key = self.key(params)
  
          # Update the parameters...
          params.update(unused)
          params.update(additional)
  
          # Get the current time
          now = time.time()
  
          # Allow up to a minute to mutate the bucket record.  If no
          # bucket exists currently, this is essentially a no-op, and
          # the bucket won't expire anyway, once the update record is
          # pushed.
          self.db.expire(key, 60)
  
          # Push an update record
          update_uuid = str(uuid.uuid4())
          update = {
              'uuid': update_uuid,
              'update': {
                  'params': params,
                  'time': now,
              },
          }
          self.db.rpush(key, msgpack.dumps(update))
  
          # Now suck in the bucket
          records = self.db.lrange(key, 0, -1)
          loader = BucketLoader(self.bucket_class, self.db, self, key, records)
  
          # Determine if we should initialize the compactor algorithm on
          # this bucket
          if 'turnstile.conf' in environ:
              config = environ['turnstile.conf']['compactor']
              try:
                  max_updates = int(config['max_updates'])
              except (KeyError, ValueError):
                  max_updates = None
              try:
                  max_age = int(config['max_age'])
              except (KeyError, ValueError):
                  max_age = 600
              if max_updates and loader.need_summary(now, max_updates, max_age):
                  # Add a summary record; we want to do this before
                  # instructing the compactor to compact.  If we did the
                  # compactor instruction first, and a crash occurred
                  # before adding the summarize record, the lack of
                  # quiesence could cause two compactor threads to run
                  # on the same bucket, leading to a race condition that
                  # could corrupt the bucket.  With this ordering, if a
                  # crash occurs before the compactor instruction, the
                  # maximum aging applied to summarize records will
                  # cause this logic to eventually be retriggered, which
                  # should allow the compactor instruction to be issued.
                  summarize = dict(summarize=now, uuid=str(uuid.uuid4()))
                  self.db.rpush(key, msgpack.dumps(summarize))
  
                  # Instruct the compactor to compact this record
                  compactor_key = config.get('compactor_key', 'compactor')
                  self.db.zadd(compactor_key, int(math.ceil(now)), key)
  
          # Set the expire on the bucket
          self.db.expireat(key, loader.bucket.expire)
  
          # If we found a delay, store the particulars in the
          # environment; this will later be sorted and an error message
          # corresponding to the longest delay returned.
          if loader.delay is not None:
              environ.setdefault('turnstile.delay', [])
              environ['turnstile.delay'].append((loader.delay, self,
                                                 loader.bucket))
  
          # Finally, if desired, add the bucket key to a desired
          # database set
          set_name = environ.get('turnstile.bucket_set')
          if set_name:
              self.db.zadd(set_name, loader.bucket.expire, key)
  
          # Should we continue the route scan?
          return not self.continue_scan