Skip to content
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

Add config store #193

Merged
merged 3 commits into from
Jun 27, 2018
Merged

Add config store #193

merged 3 commits into from
Jun 27, 2018

Conversation

kvosper
Copy link
Contributor

@kvosper kvosper commented Jun 25, 2018

Cherry-picked from previous branch to styx-1.0-dev


configStore.set("foo", "bar");
unlockedByTestThread.countDown();
unlockedBySubscribeThread.await(2, SECONDS);
Copy link
Contributor

Choose a reason for hiding this comment

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

CyclicBarrier seems more appropriate for this use case.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't know what difference that would make.

Copy link
Contributor

Choose a reason for hiding this comment

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

It would be using only one synchronising primitive instead of two. That cuts the complexity by 50% ;-).

Copy link
Contributor

Choose a reason for hiding this comment

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

I think this is conceptually much simpler:

    public void listensOnSeparateThread2() {
        final CyclicBarrier barrier = new CyclicBarrier(2);

        configStore.watch("foo", String.class)
                .subscribe(value -> {
                        await(barrier);
                });

        configStore.set("foo", "bar");
        await(barrier);
    }

Copy link
Contributor Author

Choose a reason for hiding this comment

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

OK.

/**
* Wrapper for CountDownLatch to make it more convenient to use.
*/
public class Latch {
Copy link
Contributor

Choose a reason for hiding this comment

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

As per our unwritten naming conventions, utility classes names like this would have their name pluralised.

That is, the class name should be Latches.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's not a utility class. Utility classes have only static methods. This is a normal class.

Copy link
Contributor

Choose a reason for hiding this comment

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

Right of course. Now I see that. I should have seen that straight away.

But why to implement these await methods as a composed class?

By making it a public test support class you are promoting its use in other tests. But then again the Latch class is not type compatible with CountDownLatch. Sooner or later some parts of the codebase will be using Latch while other parts stick to CountDownLatch. After that we will need to bridge the two classes at the interface level.

But all we really want is to re-propagate checked exceptions as runtime exceptions in await method.

For these reasons, please convert this to a utility class with await as a static utility method.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'll look into this.

/**
* Wrapper for CountDownLatch to make it more convenient to use.
*/
public class Latch {
Copy link
Contributor

Choose a reason for hiding this comment

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

Right of course. Now I see that. I should have seen that straight away.

But why to implement these await methods as a composed class?

By making it a public test support class you are promoting its use in other tests. But then again the Latch class is not type compatible with CountDownLatch. Sooner or later some parts of the codebase will be using Latch while other parts stick to CountDownLatch. After that we will need to bridge the two classes at the interface level.

But all we really want is to re-propagate checked exceptions as runtime exceptions in await method.

For these reasons, please convert this to a utility class with await as a static utility method.

throw new IllegalStateException(format("Latch timed out: max wait was %s %s", timeout, unit));
}
} catch (InterruptedException e) {
currentThread().interrupt();
Copy link
Contributor

Choose a reason for hiding this comment

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

Surely we need to re-throw something from the InterruptedException case? Otherwise await just returns and the calling code carries on as if nothing happened.

Copy link
Contributor

Choose a reason for hiding this comment

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

Sure I failed to notice that we had stopped throwing an Exception here. My advice is that we just let InterruptedException propagate...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Unfortunately, Observable.subscribe takes an Action1 as its argument, which will not allow InterruptedException to be thrown.

private LatchesAndBarriers() {
}

public static void await(CountDownLatch latch, long timeout, TimeUnit unit) throws IllegalStateException {
Copy link
Contributor

@dvlato dvlato Jun 26, 2018

Choose a reason for hiding this comment

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

We could have a method that receives (and returns) a lambda and catches/propagates the exception instead of this.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think the problem is with the lambda expressions. Without this utility you would be forced to try/catch inside lambda expressions.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

As Mikko says, the problem is that InterruptedException is a checked exception, and the interfaces our lambdas are implementing do not allow checked exceptions to be thrown.

Copy link
Contributor

Choose a reason for hiding this comment

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

Oh, sure. I think some of the code inside the tests uses the Latch outside a lambda.

Then my suggestion of using a method that receives a lambda (with InterruptedException in the signature) and propagates InterruptedException as a RuntimeException (but keeping the Thread.interrupt() ) makes more sense than wrapping specific classes.

Copy link
Contributor

Choose a reason for hiding this comment

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

Hi @dvlato. It no longer wraps a class. It is just a static helper method that accepts a CountDownLatch as an argument. IMO it should just set the interrupted flag and propagate an InterruptedException wrapped inside a RuntimeException.

throw new IllegalStateException(format("Latch timed out: max wait was %s %s", timeout, unit));
}
} catch (InterruptedException e) {
currentThread().interrupt();
Copy link
Contributor

Choose a reason for hiding this comment

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

Sure I failed to notice that we had stopped throwing an Exception here. My advice is that we just let InterruptedException propagate...

@mikkokar mikkokar merged commit f9eebe9 into ExpediaGroup:styx-1.0-dev Jun 27, 2018
@kvosper kvosper deleted the add-config-store branch June 27, 2018 09:35
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.

3 participants