Skip to content

API updates #325

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 15 commits into from
Mar 1, 2017
Merged

API updates #325

merged 15 commits into from
Mar 1, 2017

Conversation

lutovich
Copy link
Contributor

@lutovich lutovich commented Feb 27, 2017

This PR adds following new API methods:

  • Driver#session(String bookmark) to allow specifying initial bookmark for the session which will be used by the first transaction. This method is mainly added to bring symmetry with regards to Session#lastBookmark() and to emphasize that bookmark is a session concept.
  • Driver#session(AccessMode mode, String bookmark) to allow specifying both initial bookmark and default AccessMode per session.
  • Session#readTransaction(Function<Transaction, T> work) to allow declarative read transactions with exponential backoff retry policy.
  • Session#writeTransaction(Function<Transaction, T> work) to allow declarative write transactions with exponential backoff retry policy.
  • ConfigBuilder#withMaxTransactionRetryTime(int value, TimeUnit unit) to configure the retry policy for #readTransaction() and #writeTransaction().

It also deprecates:

  • Session#beginTransaction(String bookmark) in favour or Driver#session(bookmark)

This commit adds new API methods to create session with the specified bookmark.
This means first transaction will ensure that the server, it is connected to,
is at least up to the database version denoted by the bookmark.

Following new methods are introduced in the `Driver` interface:
 * `#session(String bookmark)`
 * `#session(AccessMode mode, String bookmark)`

Bookmark is a session related concept and this commit adds symmetry with
regards to `Session#lastBookmark()` method.
In favour of `Driver#session(String bookmark)`. This is made to bring symmetry
with regards to `Session#lastBookmark()` and emphasize that bookmark is a
session level concept.
Now it uses `Driver#session(AccessMode mode, String bookmark)` method and
does not use deprecated `Session#beginTransaction(String bookmark)`.
Commit adds two new methods to the `Session` interface to allow
declarative transactions:
 * `#readTransaction(Function<Transaction, T> work)`
 * `#writeTransaction(Function<Transaction, T> work)`

These methods currently only hide transaction creation and closing. They
return whatever the given function returns. Main reason for adding them is
that later we can hide retries behind such declarative api, which is
especially useful for "bolt+routing" driver which talks to a causal cluster.
Added ability to retry transactions executed via `Session#readTransaction()`
and `Session#writeTransaction()` methods. Given unit of work will be retried
configured number of times with configured delay if it experiences
`ServiceUnavailableException` or `SessionExpiredException`. This means it'll
be retried when a network error happens of cluster member becomes unavailable.
This commit makes routing table use same ordering of read, write and route
servers as returned by the `getServers()` procedure call. Database uses lists
to represent these servers and randomly shuffles them before returning, so
it makes sense using the provided randomized view. Is also makes boltkit
tests more predictable and easy to reason about.
`RetryWithDelayTest#throwsWhenSleepInterrupted()` test mocks throwing of
`InterruptedException` and triggers handling code to restore the interrupted
status. This caused some subsequent tests to fail because they still saw
current thread as being interrupted.

This commit adds clearing of the interrupted status to the test.
They were failing because of incorrect ports.
This commit changes default retry policy from fixed backoff to exponential
backoff with random jitter. Retry policy is user when retrying transactions
executed via `Session#readTransaction()` and `Session#writeTransaction()`
methods. Exponential backoff with random jitter is a better policy because
it spreads out clusters of retries and progressively reduces load on
the database.

The only configuration option available is:
`ConfigBuilder#withMaxTransactionRetryTime()`
which sets a cap on how long particular transaction can be retried with
exponential backoff.
}

@Override
public synchronized Transaction beginTransaction( String bookmark )
{
ensureSessionIsOpen();
ensureNoOpenTransactionBeforeOpeningTransaction();
setLastBookmark( bookmark );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why we disallow a user to set null bookmark? (It does not make many sense, but maybe a user wants to break CC from this tx?)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, I just tried to use same #setLastBookmark() method everywhere and it prohibits nulls. Will fix.


if ( decision.shouldRetry() )
{
errors = recordError( newError, errors );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we just directly chain the errors? why we have to first remember them (in recordError) and then build the error chain (in addSuppressed)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Printed stacktrace of a chain of suppressed methods looks quite strange, every next suppressed trace is shifted to the right. With this approach all previous errors will be on the same level :)

@zhenlineo
Copy link
Contributor

Looks good, minor questions. The retry logic impl is a bit scaring

@lutovich
Copy link
Contributor Author

lutovich commented Mar 1, 2017

Thanks @zhenlineo! I agree about retry logic, will try to simplify it in subsequent PRs. There is no point in having separate RetryLogic and RetryDecision...

So it is possible to "break" causal consistency within a session by
calling `#beginTransaction(null)`.
@zhenlineo zhenlineo merged commit c47aa01 into neo4j:1.2 Mar 1, 2017
@lutovich lutovich deleted the 1.2-new-api branch March 1, 2017 11:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants