def test_pop_pending_limit(self):
        k = pending_key('test')

        for t in range(5, 40, 5):
            yield add_pending(self.redis, 'test', {
                'owner_id': '1234',
                'timestamp': t,
                'attempts': 0,
                'intervals': [10],
                'request': {'foo': t}
            })

        pending = yield zitems(self.redis, k)
        pending_reqs = [r for t, r in pending]

        result = yield pop_pending(self.redis, 'test', 0, 50, limit=2)
        self.assertEqual(result, pending_reqs[:2])
        self.assertEqual((yield zitems(self.redis, k)), pending[2:])

        result = yield pop_pending(self.redis, 'test', 0, 50, limit=3)
        self.assertEqual(result, pending_reqs[2:5])
        self.assertEqual((yield zitems(self.redis, k)), pending[5:])

        result = yield pop_pending(self.redis, 'test', 0, 50, limit=3)
        self.assertEqual(result, pending_reqs[5:])
        self.assertEqual((yield zitems(self.redis, k)), [])

        result = yield pop_pending(self.redis, 'test', 0, 50, limit=3)
        self.assertEqual(result, [])
        self.assertEqual((yield zitems(self.redis, k)), [])
Esempio n. 2
0
    def route_requests(self, req, body):
        owner_id = req.getHeader('x-owner-id')
        req_limit = self.config.request_limit

        if (yield self.req_limit_reached(owner_id)):
            self.log(
                "Request limit reached for %s at a request count of %d"
                % (owner_id, req_limit))

            returnValue(response(req, {
                'errors': [{
                    'type': 'too_many_requests',
                    'message': (
                        "Only %d unfinished requests are allowed per owner"
                        % (req_limit))
                }]
            }, code=429))
        else:
            data = {
                'owner_id': req.getHeader('x-owner-id'),
                'timestamp': time.time(),
                'request': body['request'],
                'intervals': body['intervals']
            }

            self.log("Adding request to pending set", data)
            yield add_pending(self.redis, self.prefix, data)
            yield inc_req_count(self.redis, self.prefix, owner_id)
            returnValue(response(req, {}))
    def test_add_pending_next_retry(self):
        k = pending_key('test')
        self.assertEqual((yield zitems(self.redis, k)), [])

        yield add_pending(self.redis, 'test', {
            'owner_id': '1234',
            'timestamp': 10,
            'attempts': 1,
            'intervals': [50, 60],
            'request': {'foo': 23}
        })

        self.assertEqual((yield zitems(self.redis, k)), [
            (10 + 60, {
                'owner_id': '1234',
                'timestamp': 10,
                'attempts': 1,
                'intervals': [50, 60],
                'request': {'foo': 23},
            }),
        ])

        yield add_pending(self.redis, 'test', {
            'owner_id': '1234',
            'timestamp': 5,
            'attempts': 2,
            'intervals': [20, 90, 100],
            'request': {'bar': 42}
        })

        self.assertEqual((yield zitems(self.redis, k)), [
            (10 + 60, {
                'owner_id': '1234',
                'timestamp': 10,
                'attempts': 1,
                'intervals': [50, 60],
                'request': {'foo': 23},
            }),
            (5 + 100, {
                'owner_id': '1234',
                'timestamp': 5,
                'attempts': 2,
                'intervals': [20, 90, 100],
                'request': {'bar': 42},
            }),
        ])
    def test_maintain(self):
        k_p = pending_key('test')
        k_r = ready_key('test')

        worker = yield self.mk_worker({
            'redis_prefix': 'test',
            'frequency': 20,
        })

        worker.stop()

        for t in range(5, 25, 5):
            yield add_pending(worker.redis, 'test', {
                'owner_id': '1234',
                'timestamp': t,
                'attempts': 0,
                'intervals': [10],
                'request': {'foo': t}
            })

        pending = yield zitems(worker.redis, pending_key('test'))
        pending_reqs = [v for t, v in pending]

        worker.clock.advance(10)
        self.assertEqual((yield lvalues(worker.redis, k_r)), [])
        self.assertEqual((yield zitems(worker.redis, k_p)), pending)
        yield worker.maintain()
        self.assertEqual((yield lvalues(worker.redis, k_r)), [])
        self.assertEqual((yield zitems(worker.redis, k_p)), pending)

        worker.clock.advance(5)
        self.assertEqual((yield lvalues(worker.redis, k_r)), [])
        self.assertEqual((yield zitems(worker.redis, k_p)), pending)
        yield worker.maintain()
        self.assertEqual((yield lvalues(worker.redis, k_r)), pending_reqs[:1])
        self.assertEqual((yield zitems(worker.redis, k_p)), pending[1:])

        worker.clock.advance(10)
        self.assertEqual((yield lvalues(worker.redis, k_r)), pending_reqs[:1])
        self.assertEqual((yield zitems(worker.redis, k_p)), pending[1:])
        yield worker.maintain()
        self.assertEqual((yield lvalues(worker.redis, k_r)), pending_reqs[:3])
        self.assertEqual((yield zitems(worker.redis, k_p)), pending[3:])

        worker.clock.advance(5)
        self.assertEqual((yield lvalues(worker.redis, k_r)), pending_reqs[:3])
        self.assertEqual((yield zitems(worker.redis, k_p)), pending[3:])
        yield worker.maintain()
        self.assertEqual((yield lvalues(worker.redis, k_r)), pending_reqs)
        self.assertEqual((yield zitems(worker.redis, k_p)), [])
    def test_pop_pending_add_ready(self):
        k_p = pending_key('test')
        k_r = ready_key('test')

        for t in range(5, 40, 5):
            yield add_pending(self.redis, 'test', {
                'owner_id': '1234',
                'timestamp': t,
                'attempts': 0,
                'intervals': [10],
                'request': {'foo': t}
            })

        pending_reqs = [r for t, r in (yield zitems(self.redis, k_p))]

        yield pop_pending_add_ready(self.redis, 'test', 0, 50)

        self.assertEqual((yield lvalues(self.redis, k_r)), pending_reqs)
        self.assertEqual((yield zitems(self.redis, k_p)), [])
    def test_pop_pending_no_deserialize(self):
        k = pending_key('test')

        for t in range(5, 35, 5):
            yield add_pending(self.redis, 'test', {
                'owner_id': '1234',
                'timestamp': t,
                'attempts': 0,
                'intervals': [10],
                'request': {'foo': t}
            })

        pending = yield zitems(self.redis, k)
        pending_reqs = [r for t, r in pending]

        result = yield pop_pending(
            self.redis, 'test', 0, 10 + 13, deserialize=False)

        self.assertEqual([json.loads(r) for r in result], pending_reqs[:2])
    def test_pop_pending_add_ready_chunks_tap(self):
        k_p = pending_key('test')
        taps = []

        for t in range(5, 40, 5):
            yield add_pending(self.redis, 'test', {
                'owner_id': '1234',
                'timestamp': t,
                'attempts': 0,
                'intervals': [10],
                'request': {'foo': t}
            })

        pending_reqs = yield self.redis.zrange(k_p, 0, -1)

        yield pop_pending_add_ready(
            self.redis, 'test', 0, 50, chunk_size=3, tap=taps.append)

        self.assertEqual(taps, [
            pending_reqs[:3],
            pending_reqs[3:6],
            pending_reqs[6:],
        ])
    def test_pop_pending_add_ready_chunks(self):
        calls = self.redis_spy('zrangebyscore')

        k = pending_key('test')

        for t in range(5, 40, 5):
            yield add_pending(self.redis, 'test', {
                'owner_id': '1234',
                'timestamp': t,
                'attempts': 0,
                'intervals': [10],
                'request': {'foo': t}
            })

        yield pop_pending_add_ready(
            self.redis, 'test', 0, 50, chunk_size=3)

        self.assertEqual(calls, 4 * [
            ((k, 0, 50), {
                'offset': 0,
                'count': 3
            }),
        ])
    def test_loop(self):
        k_p = pending_key('test')
        k_r = ready_key('test')

        msgs = self.patch_log()

        worker = yield self.mk_worker({
            'redis_prefix': 'test',
            'frequency': 5,
        })

        for t in range(5, 25, 5):
            yield add_pending(worker.redis, 'test', {
                'owner_id': '1234',
                'timestamp': t,
                'attempts': 0,
                'intervals': [10],
                'request': {'foo': t}
            })

        pending = yield zitems(worker.redis, pending_key('test'))
        pending_reqs = [v for t, v in pending]

        self.assertEqual(pop_all(msgs), [
            'Checking for requests to move from pending to ready',
        ])

        worker.maintains.pop()

        worker.clock.advance(5)
        yield worker.maintains.pop()
        self.assertEqual((yield lvalues(worker.redis, k_r)), [])
        self.assertEqual((yield zitems(worker.redis, k_p)), pending)

        self.assertEqual(pop_all(msgs), [
            'Checking for requests to move from pending to ready',
        ])

        worker.clock.advance(5)
        yield worker.maintains.pop()
        self.assertEqual((yield lvalues(worker.redis, k_r)), [])
        self.assertEqual((yield zitems(worker.redis, k_p)), pending)

        self.assertEqual(pop_all(msgs), [
            'Checking for requests to move from pending to ready',
        ])

        worker.clock.advance(5)
        yield worker.maintains.pop()
        self.assertEqual((yield lvalues(worker.redis, k_r)), pending_reqs[:1])
        self.assertEqual((yield zitems(worker.redis, k_p)), pending[1:])

        self.assertEqual(pop_all(msgs), [
            'Checking for requests to move from pending to ready',
            '1 request(s) moved from pending to ready',
        ])

        worker.clock.advance(5)
        yield worker.maintains.pop()
        self.assertEqual((yield lvalues(worker.redis, k_r)), pending_reqs[:2])
        self.assertEqual((yield zitems(worker.redis, k_p)), pending[2:])

        self.assertEqual(pop_all(msgs), [
            'Checking for requests to move from pending to ready',
            '1 request(s) moved from pending to ready',
        ])

        worker.clock.advance(5)
        yield worker.maintains.pop()
        self.assertEqual((yield lvalues(worker.redis, k_r)), pending_reqs[:3])
        self.assertEqual((yield zitems(worker.redis, k_p)), pending[3:])

        self.assertEqual(pop_all(msgs), [
            'Checking for requests to move from pending to ready',
            '1 request(s) moved from pending to ready',
        ])

        worker.clock.advance(5)
        yield worker.maintains.pop()
        self.assertEqual((yield lvalues(worker.redis, k_r)), pending_reqs)
        self.assertEqual((yield zitems(worker.redis, k_p)), [])

        self.assertEqual(pop_all(msgs), [
            'Checking for requests to move from pending to ready',
            '1 request(s) moved from pending to ready',
        ])

        self.assertEqual(worker.maintains, [])

        worker.stop()
        worker.clock.advance(5)

        self.assertEqual(worker.maintains, [])
        self.assertEqual(pop_all(msgs), [])