def test_status(parts, monkeypatch):
    """New job shows all parts remaining
    """
    monkeypatch.setenv('WorkTopic', 'abc123')
    with patch('redis.StrictRedis', mock_strict_redis_client):
        p = RedisProgress()
        p.set_total('123', parts)
        status = p.status('123')
        assert status['total'] == 3
        assert status['remaining'] == 3
        assert status['progress'] == 0
def test_no_delete_when_done(parts, monkeypatch):
    p = RedisProgress(host='localhost', port=6379, db=0, topic_arn='nope', delete_when_done=False)
    jobid = '123'
    p.set_total(jobid, [parts[0]])
    assert len(list(p.list_pending_parts(jobid))) == 1
    p.complete_part(jobid, 0)
    assert 'total' in p._decode_dict(p.redis.hgetall('123-metadata'))
    assert p.status(jobid)['remaining'] == 0  # status still works
def test_delete(parts, monkeypatch):
    p = RedisProgress(host='localhost', port=6379, db=0, topic_arn='nope')
    jobid = '123'
    p.set_total(jobid, parts)
    assert 'total' in p.status(jobid)
    p.delete(jobid)
    with pytest.raises(JobDoesNotExist):
        p.status(jobid)
def test_list_pending_nojobs(parts, monkeypatch):
    p = RedisProgress(host='localhost', port=6379, db=0, topic_arn='nope')
    jobid = '123'
    p.set_total(jobid, parts)
    assert len(list(p.list_pending_parts(jobid))) == 3
    p.delete(jobid)
    with pytest.raises(JobDoesNotExist):
        p.list_pending_parts(jobid)
def test_delete_when_done(parts, monkeypatch):
    p = RedisProgress(host='localhost', port=6379, db=0, topic_arn='nope', delete_when_done=True)
    jobid = '123'
    p.set_total(jobid, [parts[0]])
    assert len(list(p.list_pending_parts(jobid))) == 1
    p.complete_part(jobid, 0)
    assert not p.redis.hgetall('123-metadata')
    with pytest.raises(JobDoesNotExist):
        p.status(jobid)
def test_list_pending(parts, monkeypatch):
    p = RedisProgress(host='localhost', port=6379, db=0, topic_arn='nope')
    jobid = '123'
    p.set_total(jobid, parts)
    assert len(list(p.list_pending_parts(jobid))) == 3
    p.complete_part(jobid, 0)
    assert len(list(p.list_pending_parts(jobid))) == 2
def test_status_no_total(monkeypatch):
    """ Have not created a job with .set_total() yet
    """
    monkeypatch.setenv('WorkTopic', 'abc123')
    with patch('redis.StrictRedis', mock_strict_redis_client):
        with pytest.raises(JobDoesNotExist):
            RedisProgress().status('123')
Exemple #8
0
def main(backend, number):
    if backend == 'redis':
        progress = RedisProgress(host='localhost', port='6379')
    elif backend == 'dynamodb':
        progress = DynamoProgress()

    parts = [dict() for _ in range(number)]
    workers = 25

    # Simulates Subject:start messages
    jobid = create_job(parts, progress=progress, workers=workers)

    # Simulates concurrent Subject:map messages
    # The annonate_parts function recreates the messages that would be recieved
    msgs = annotate_parts(parts, jobid)

    def doit(msg, jobid=jobid, progress=progress):
        partid = msg['partid']
        with Part(partid=partid, jobid=jobid, progress=progress):
            pass

    with futures.ThreadPoolExecutor(max_workers=workers) as executor:
        executor.map(doit, msgs)

    print(f"completed watchbot progress for {number} parts using {progress}")
def test_progress_all_done(aws_send_message, sns_worker, monkeypatch):
        monkeypatch.setenv('WorkTopic', 'abc123')
        progress = RedisProgress()

        jobid = create_job(parts, progress=progress)
        for i in range(3):
            with Part(jobid, i, progress=progress):
                pass

        assert progress.status(jobid)['remaining'] == 0

        # 3 map messages and 1 reduce message sent
        sns_worker.assert_called_once()
        assert len(sns_worker.call_args[0][0]) == 3
        assert sns_worker.call_args[1].get('subject') == 'map'
        aws_send_message.assert_called_once()
        assert aws_send_message.call_args[1].get('subject') == 'reduce'
def test_progress_one_done(aws_send_message, sns_worker, monkeypatch):
        monkeypatch.setenv('WorkTopic', 'abc123')

        sns_worker.side_effect = [True]

        progress = RedisProgress()

        jobid = create_job(parts, progress=progress)
        with Part(jobid, 0, progress=progress):
            pass

        assert progress.status(jobid)['remaining'] == 2

        # 3 map messages, No reduce message sent
        sns_worker.assert_called_once()
        assert len(sns_worker.call_args[0][0]) == 3
        assert sns_worker.call_args[1].get('subject') == 'map'
        aws_send_message.assert_not_called()
def test_metadata(parts, monkeypatch):
    """Setting and getting job metadata works
    """
    monkeypatch.setenv('WorkTopic', 'abc123')
    with patch('redis.StrictRedis', mock_strict_redis_client):
        p = RedisProgress()
        p.set_total('123', parts)
        p.set_metadata('123', {'test': 'foo'})
        assert p.status('123')['metadata']['test'] == 'foo'
def test_failjob(parts, monkeypatch):
    """Mark job as failed works
    """
    monkeypatch.setenv('WorkTopic', 'abc123')
    with patch('redis.StrictRedis', mock_strict_redis_client):
        p = RedisProgress()
        p.set_total('123', parts)
        p.fail_job('123', 'epic fail')
        assert p.status('123')['failed'] is True
def test_status_part(parts, monkeypatch):
    """Check if part is complete
    """
    monkeypatch.setenv('WorkTopic', 'abc123')
    with patch('redis.StrictRedis', mock_strict_redis_client):
        p = RedisProgress()
        p.set_total('123', parts)
        p.complete_part('123', 0)

        assert p.status('123', part=0)['complete'] is True
        assert p.status('123', part=1)['complete'] is False
def test_status_complete_some(parts, monkeypatch):
    """job shows partial progress
    """
    monkeypatch.setenv('WorkTopic', 'abc123')
    with patch('redis.StrictRedis', mock_strict_redis_client):
        p = RedisProgress()
        p.set_total('123', parts)
        done_yet = p.complete_part('123', 0)
        assert not done_yet

        status = p.status('123')
        assert status['total'] == 3
        assert status['remaining'] == 2
        assert status['progress'] == 1 / 3
def test_status_complete_all(parts, monkeypatch):
    """job shows complete progress
    """
    monkeypatch.setenv('WorkTopic', 'abc123')
    with patch('redis.StrictRedis', mock_strict_redis_client):
        p = RedisProgress()
        p.set_total('123', parts)
        for i, _ in enumerate(parts):
            done_yet = p.complete_part('123', i)
        assert done_yet

        status = p.status('123')
        assert status['total'] == 3
        assert status['remaining'] == 0
        assert status['progress'] == 1.0
Exemple #16
0
def validate_db(ctx, param, value):
    topic_arn = 'should-never-need-to-use-SNS'

    if value.startswith('redis'):
        url = urlparse(value)
        assert url.scheme == 'redis'

        db = 0
        if url.query:
            queries = url.query.split('&')
            for query in queries:
                k, v = query.split('=')
                if k == 'db':
                    db = int(v)

        host, port = url.netloc.split(":")
        return RedisProgress(host=host, port=port, db=db, topic_arn=topic_arn)

    elif value.startswith('arn:'):
        return DynamoProgress(table_arn=value, topic_arn=topic_arn)

    else:
        raise click.BadParameter('Needs to be {}'.format(DBHELP))
def test_progress_reduce_once(aws_send_message, sns_worker, monkeypatch):
        """Ensure that reduce message is only sent once,
        even if parts are completed multiple times
        """
        monkeypatch.setenv('WorkTopic', 'abc123')
        progress = RedisProgress()
        jobid = create_job(parts, progress=progress)

        for i in range(3):
            with Part(jobid, i, progress=progress):
                pass
        aws_send_message.assert_called_once()
        assert aws_send_message.call_args[1].get('subject') == 'reduce'

        aws_send_message.reset_mock()

        # Finishing already completed parts should not trigger reduce message, only warn
        with pytest.warns(UserWarning) as record:
            for i in range(3):
                with Part(jobid, i, progress=progress):
                    pass
        assert 'skip' in record[0].message.args[0]
        aws_send_message.assert_not_called()
def test_list_jobids(parts, monkeypatch):
    p = RedisProgress(host='localhost', port=6379, db=0, topic_arn='nope')
    p.set_total('job1', parts)
    p.set_total('job2', parts)
    assert list(p.list_jobs(status=False)) == ['job1', 'job2']
Exemple #19
0
from . import version as app_version

from cogeo_mosaic.utils import (
    _aws_get_data,
    _aws_put_data,
    _compress_gz_json,
    create_mosaic,
    get_hash,
)

logger = logging.getLogger("watchbot")
logger.setLevel(logging.INFO)

progress = RedisProgress(
    host=os.environ["REDIS_DB_HOST"],
    port=os.environ["REDIS_DB_PORT"],
    topic_arn=os.environ["SNS_TOPIC"],
)


class LambdaFileIsTooBig(Exception):
    """File is too big for AWS Lambda."""


def _aws_list_objects(bucket, prefix):
    """List object in a bucket."""
    session = boto3_session()
    client = session.client("s3")
    pag = client.get_paginator("list_objects_v2")

    files = []
def test_list_jobs_meta(parts, monkeypatch):
    p = RedisProgress(host='localhost', port=6379, db=0, topic_arn='nope')
    p.set_total('job1', parts)
    p.set_total('job2', parts)
    p.redis.delete('job1-parts')  # job1-metdata should remain thus still be in list
    assert len(list(p.list_jobs())) == 2
def test_list_jobs(parts, monkeypatch):
    p = RedisProgress(host='localhost', port=6379, db=0, topic_arn='nope')
    p.set_total('job1', parts)
    p.set_total('job2', parts)
    assert len(list(p.list_jobs())) == 2