def test_size_limit_option(db): value = b'a' * 1024 setValue(db, b't1', value) assert(value == db[b't1']) try: db.options.set_transaction_size_limit(1000) setValue(db, b't2', value) assert(False) # not reached except fdb.FDBError as e: assert(e.code == 2101) # Transaction exceeds byte limit (2101) # Per transaction option overrides database option db.options.set_transaction_size_limit(1000000) try: setValueWithLimit(db, b't3', value, 1000) assert(False) # not reached except fdb.FDBError as e: assert(e.code == 2101) # Transaction exceeds byte limit (2101) # DB default survives on_error reset db.options.set_transaction_size_limit(1000) tr = db.create_transaction() try: tr[b't4'] = b'bar' tr.on_error(fdb.FDBError(1007)).wait() setValue(tr, b't4', value) tr.commit().wait() assert(False) # not reached except fdb.FDBError as e: assert(e.code == 2101) # Transaction exceeds byte limit (2101)
def txn2(tr): tr.options.set_timeout(100) tr.on_error(fdb.FDBError(1007)).wait() # should not throw time.sleep(1) try: tr.commit().wait() # should throw except fdb.FDBError as e: if e.code != 1031: raise
def txn1(tr): tr.options.set_retry_limit(0) tr.options.set_timeout(100) try: tr.on_error(fdb.FDBError(1007)).wait() # should throw raise TestError("Retry limit was ignored.") except fdb.FDBError as e: if e.code != 1007: raise time.sleep(1) tr.commit().wait() # should not throw
def txn8(tr): tr[b'foo'] = b'bar' time.sleep(1) tr.on_error(fdb.FDBError(1007)).wait() # should not throw tr[b'foo'] = b'bar' tr.options.set_timeout(100) try: tr.commit().wait() # should throw raise TestError("Timeout didn't fire.") except fdb.FDBError as e: if e.code != 1031: raise
def txn3(tr): tr.cancel() try: tr.on_error(fdb.FDBError(1007)).wait() # should throw raise TestError('on_error() did not notice cancellation.') except fdb.FDBError as e: if e.code != 1025: raise try: tr.commit().wait() # should throw raise TestError('Cancellation did not survive on_error().') except fdb.FDBError as e: if e.code != 1025: raise
def txn11(tr): for i in range(2): tr.options.set_timeout(1500) tr.set_read_version(0x7ffffffffffffff0) x = tr[b'foo'] try: tr.commit().wait() tr.reset() except fdb.FDBError as e: if i == 0: if e.code != 1009: # future_version raise fdb.FDBError(1007) # Something weird happened; raise a retryable error so we run this transaction again else: tr.on_error(e).wait() elif i == 1 and e.code != 1031: raise
def wait_empty(tr, prefix): res = tr.get_range_startswith(prefix, 1).to_list() if len(res) == 1: raise fdb.FDBError(1020)
def test_predicates(): assert fdb.predicates.is_retryable(fdb.FDBError(1020)) assert not fdb.predicates.is_retryable(fdb.FDBError(10))
def txn2(tr): tr.options.set_timeout(100) tr.on_error(fdb.FDBError(1007)).wait() # should not throw time.sleep(1) tr.commit().wait() # should not throw
def test_retry_limits(db): err = fdb.FDBError(1007) # (1) Basic retry limits @retry_with_timeout(default_timeout) def txn1(tr): tr.options.set_retry_limit(1) tr[b'foo'] = b'bar' tr.on_error(err).wait() # should not throw tr[b'foo'] = b'bar' tr.options.set_retry_limit(1) try: tr.on_error(err).wait() # should throw raise TestError('(1) Retry limit was ignored.') except fdb.FDBError as e: if e.code != 1007: raise tr[b'foo'] = b'bar' tr.options.set_retry_limit(1) try: tr.on_error(err).wait() # should throw raise TestError('(1) Retry limit was ignored.') except fdb.FDBError as e: if e.code != 1007: raise txn1(db) # (2) Number of retries accumulates even when limit is being hit @retry_with_timeout(default_timeout) def txn2(tr): tr.options.set_retry_limit(0) tr[b'foo'] = b'bar' try: tr.on_error(err).wait() # should throw raise TestError('(2) Retry limit was ignored.') except fdb.FDBError as e: if e.code != 1007: raise tr.options.set_retry_limit(1) tr[b'foo'] = b'bar' try: tr.on_error(err).wait() # should throw raise TestError('(2) Retry limit was ignored.') except fdb.FDBError as e: if e.code != 1007: raise txn2(db) # (3) Retry limits don't survive resets @retry_with_timeout(default_timeout) def txn3(tr): tr.options.set_retry_limit(1) tr[b'foo'] = b'bar' tr.on_error(err).wait() # should not throw tr.options.set_retry_limit(1) tr[b'foo'] = b'bar' try: tr.on_error(err).wait() # should throw raise TestError('(3) Retry limit was ignored.') except fdb.FDBError as e: if e.code != 1007: raise tr.reset() tr[b'foo'] = b'bar' tr.on_error(err).wait() # should not throw txn3(db) # (4) Number of retries does not survive resets @retry_with_timeout(default_timeout) def txn4(tr): tr.options.set_retry_limit(0) tr[b'foo'] = b'bar' try: tr.on_error(err).wait() # should throw raise TestError('(4) Retry limit was ignored.') except fdb.FDBError as e: if e.code != 1007: raise tr.reset() tr.options.set_retry_limit(1) tr[b'foo'] = b'bar' tr.on_error(err).wait() # should not throw txn4(db) # (5) Retries accumulate when limits are turned off, and are respected retroactively @retry_with_timeout(default_timeout) def txn5(tr): tr[b'foo'] = b'bar' tr.on_error(err).wait() # should not throw tr[b'foo'] = b'bar' tr.on_error(err).wait() # should not throw tr.options.set_retry_limit(1) try: tr.on_error(err).wait() # should throw raise TestError('(5) Retry limit was ignored.') except fdb.FDBError as e: if e.code != 1007: raise tr[b'foo'] = b'bar' tr.options.set_retry_limit(-1) tr.on_error(err).wait() # should not throw tr.options.set_retry_limit(4) try: tr.on_error(err).wait() # should throw raise TestError('(5) Retry limit was ignored.') except fdb.FDBError as e: if e.code != 1007: raise txn5(db) # (6) Retry limits don't survive on_error() @retry_with_timeout(default_timeout) def txn6(tr): tr.options.set_retry_limit(1) tr[b'foo'] = b'bar' tr.on_error(err).wait() # should not throw tr[b'foo'] = b'bar' tr.options.set_retry_limit(1) try: tr.on_error(err).wait() # should throw raise TestError('(6) Retry limit was ignored.') except fdb.FDBError as e: if e.code != 1007: raise tr[b'foo'] = b'bar' tr.on_error(err).wait() # should not throw txn6(db)
def test_db_timeouts(db): err = fdb.FDBError(1007) db.options.set_transaction_timeout(500) # (1) Basic timeout @retry_with_timeout(default_timeout) def txn1(tr): time.sleep(1) try: tr.commit().wait() # should throw raise TestError("(1) Timeout didn't fire.") except fdb.FDBError as e: if e.code != 1031: raise txn1(db) # (2) Timeout after on_error @retry_with_timeout(default_timeout) def txn2(tr): tr[b'foo'] = b'bar' tr.on_error(err).wait() # should not throw time.sleep(1) tr[b'foo'] try: tr.commit().wait() # should throw raise TestError("(2) Timeout didn't fire.") except fdb.FDBError as e: if e.code != 1031: raise txn2(db) # (3) Longer timeout than database timeout @retry_with_timeout(default_timeout) def txn3(tr): tr.options.set_timeout(1000) time.sleep(0.75) tr[b'foo'] = b'bar' tr.on_error(err).wait() # should not throw tr[b'foo'] time.sleep(0.75) try: tr.commit().wait() # should throw raise TestError("(3) Timeout didn't fire.") except fdb.FDBError as e: if e.code != 1031: raise txn3(db) # (4) Shorter timeout than database timeout @retry_with_timeout(default_timeout) def txn4(tr): tr.options.set_timeout(100) tr[b'foo'] = b'bar' time.sleep(0.2) try: tr.commit().wait() # should throw raise TestError("(4) Timeout didn't fire.") except fdb.FDBError as e: if e.code != 1031: raise txn4(db) # (5) Reset resets timeout to database timeout @retry_with_timeout(default_timeout) def txn5(tr): tr.options.set_timeout(100) tr[b'foo'] = b'bar' time.sleep(0.2) try: tr.commit().wait() # should throw raise TestError("(5) Timeout didn't fire.") except fdb.FDBError as e: if e.code != 1031: raise tr.reset() tr[b'foo'] = b'bar' time.sleep(0.2) tr.on_error(err).wait() #should not throw tr[b'foo'] = b'bar' time.sleep(0.8) try: tr.commit().wait() # should throw raise TestError("(5) Timeout didn't fire.") except fdb.FDBError as e: if e.code != 1031: raise txn5(db) db.options.set_transaction_timeout(0) # reset to default (no timeout)
def test_db_retry_limits(db): err = fdb.FDBError(1007) db.options.set_transaction_retry_limit(1) # (1) Basic retry limit @retry_with_timeout(default_timeout) def txn1(tr): tr[b'foo'] = b'bar' tr.on_error(err).wait() # should not throw tr[b'foo'] = b'bar' try: tr.on_error(err).wait() # should throw raise TestError('(1) Retry limit from database was ignored.') except fdb.FDBError as e: if e.code != err.code: raise tr[b'foo'] = b'bar' try: tr.on_error(err).wait() # should throw raise TestError('(1) Transaction not cancelled after error.') except fdb.FDBError as e: if e.code != 1025: raise txn1(db) # (2) More retries in transaction than database @retry_with_timeout(default_timeout) def txn2(tr): tr.options.set_retry_limit(2) tr[b'foo'] = b'bar' tr.on_error(err).wait() # should not throw tr[b'foo'] = b'bar' tr.on_error(err).wait() # should not throw tr[b'foo'] = b'bar' try: tr.on_error(err).wait() # should throw raise TestError('(2) Retry limit from transaction was ignored.') except fdb.FDBError as e: if e.code != err.code: raise tr[b'foo'] = b'bar' try: tr.on_error(err).wait() # should throw raise TestError('(2) Transaction not cancelled after error.') except fdb.FDBError as e: if e.code != 1025: raise txn2(db) # (3) More retries in database than transaction db.options.set_transaction_retry_limit(2) @retry_with_timeout(default_timeout) def txn3(tr): tr.options.set_retry_limit(1) tr[b'foo'] = b'bar' tr.on_error(err).wait() # should not throw tr[b'foo'] = b'bar' try: tr.on_error(err).wait() # should throw raise TestError('(3) Retry limit from transaction was ignored.') except fdb.FDBError as e: if e.code != err.code: raise tr[b'foo'] = b'bar' try: tr.on_error(err).wait() # should throw raise TestError('(3) Transaction not cancelled after error.') except fdb.FDBError as e: if e.code != 1025: raise txn3(db) # (4) Reset resets to database default @retry_with_timeout(default_timeout) def txn4(tr): tr.options.set_retry_limit(1) tr[b'foo'] = b'bar' tr.on_error(err).wait() # should not throw tr[b'foo'] = b'bar' try: tr.on_error(err).wait() # should throw raise TestError('(4) Retry limit from transaction was ignored.') except fdb.FDBError as e: if e.code != err.code: raise tr.reset() tr[b'foo'] = b'bar' tr.on_error(err).wait() # should not throw tr[b'foo'] = b'bar' tr.on_error(err).wait() # should not throw tr[b'foo'] = b'bar' try: tr.on_error(err).wait() # should throw raise TestError('(4) Retry limit from database was ignored.') except fdb.FDBError as e: if e.code != err.code: raise try: tr.on_error(err).wait() # should throw raise TestError('(4) Transaction not cancelled after error.') except fdb.FDBError as e: if e.code != 1025: raise txn4(db) db.options.set_transaction_retry_limit( -1) # reset to default (infinite retries)