Example #1
0
def test_threeway_merge():
    qa = qube.init({'name': 'zoidberg', 'number': 5, 'value': 10})
    qube.apply_op(qa, ('change', 'number', (5, 6), 'tx001'))

    qb = qube.from_json(qube.to_json(qa))
    qc = qube.from_json(qube.to_json(qa))

    qube.apply_op(qa, ('change', 'name', ('zoidberg', 'bob'), 'tx002'))
    qube.apply_op(qb, ('change', 'number', (6, 7), 'tx003'))
    qube.apply_op(qc, ('change', 'value', (10, 9), 'tx004'))

    error, watch = track_error()

    m = qube.merge(qa, qb, qc, error=watch)
    assert_that(m, has_entry('sequence', 4))
    assert_that(m, has_entry('data', has_entry('name', 'bob')))
    assert_that(m, has_entry('data', has_entry('number', 7)))
    assert_that(m, has_entry('data', has_entry('value', 9)))

    assert_that(error, has_length(0))
Example #2
0
def test_step_merge_bside():
    qa = qube.init({'name': 'zoidberg', 'number': 5, 'value': 10})
    qube.apply_op(qa, ('change', 'number', (5, 6), 'tx001'))

    qb = qube.from_json(qube.to_json(qa))

    qube.apply_op(qa, ('change', 'name', ('zoidberg', 'bob'), 'tx002'))
    qube.apply_op(qb, ('change', 'number', (6, 7), 'tx004'))

    qc = qube.from_json(qube.to_json(qb))
    qube.apply_op(qc, ('change', 'value', (10, 9), 'tx004'))

    pprint(qa)
    pprint(qb)
    pprint(qc)

    error, watch = track_error()
    ma = qube.merge(qa, qb, error=watch)

    assert_that(error, has_length(0))
    assert_that(ma, has_entry('sequence', 3))
    assert_that(ma, has_entry('data', has_entry('name', 'bob')))
    assert_that(ma, has_entry('data', has_entry('number', 7)))
    assert_that(ma, has_entry('data', has_entry('value', 10)))

    print('---')
    pprint(ma)
    pprint(qc)

    error, watch = track_error()
    mb = qube.merge(ma, qc, error=watch)
    assert_that(error, has_length(0))
    assert_that(mb, has_entry('sequence', 4))
    assert_that(mb, has_entry('data', has_entry('name', 'bob')))
    assert_that(mb, has_entry('data', has_entry('number', 7)))
    assert_that(mb, has_entry('data', has_entry('value', 9)))
Example #3
0
File: model.py Project: keis/lera
    def read(cls, db, rollback, key):
        logger.debug("reading %s/%s", cls.bucket, key)

        modified = False
        rollbacks = rollback.txs

        @contextlib.contextmanager
        def queue_rollback(op):
            try:
                yield
            except Exception as e:
                logger.debug('operation failed %r', op)
                cls.queue_rollback(rollback, op)

        try:
            response = yield from db.get(cls.bucket, key)

        except riak.Conflict as e:
            logger.debug("conflict in %s/%s", cls.bucket, key)
            modified = True
            first = e.siblings.pop()

            links = first.links
            vclock = e.vclock
            data = qube.from_json(first)

            for tx in rollbacks:
                qube.rollback(data, tx, error=queue_rollback)

            for r in e.siblings:
                r = qube.from_json(r)

                for tx in rollbacks:
                    qube.rollback(r, tx, error=queue_rollback)

                data = qube.merge(data, r, error=queue_rollback)

        except:
            logger.error("Other error reading", exc_info=True)
            raise

        else:
            links = response.links
            vclock = response.vclock
            data = qube.from_json(response)

            if rollbacks:
                logger.debug("processing rollbacks in %s/%s %r", cls.bucket, key, rollbacks)

                try:
                    seq = data['sequence']
                    for tx in rollbacks:
                        data = qube.rollback(data, tx, error=queue_rollback)
                    modified = seq != data['sequence']
                except:
                    logger.error("error performing rollback", exc_info=True)
                    raise

        model = cls(key, data, vclock=vclock, links=links)

        if modified:
            # Ideally this would happen after returning the list
            # TODO: Task()
            yield from model.save(db)
            yield from rollback.process(db)

        logger.debug('read %s/%s %s', cls.bucket, key, vclock)
        return model