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 CentralDogma backed EndpointGroup #105

Merged
merged 9 commits into from May 11, 2018
Merged

Conversation

imasahiro
Copy link
Member

Note: Special thanks to @huydx who is the initial author of
CentralDogmaEndpointGroup(line/armeria#828)

@huydx
Copy link
Contributor

huydx commented Dec 13, 2017

there's no unit test yet, or you will add it later?

/**
* A CentralDogma based {@link EndpointGroup} implementation. This {@link EndpointGroup} retrieves the list of
* {@link Endpoint}s from a route file served by CentralDogma, and update the list when upstream data changes.
* Route file could be json file or normal text file.
Copy link
Member

Choose a reason for hiding this comment

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

s/json/JSON/g

* {@link Endpoint}s from a route file served by CentralDogma, and update the list when upstream data changes.
* Route file could be json file or normal text file.
* <p>
* <p>In below example, json file with below content will be served as route file:
Copy link
Member

Choose a reason for hiding this comment

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

For example, the following JSON file will be served as a route file:

* "host3:port3"
* ]
* }
* </pre>
Copy link
Member

Choose a reason for hiding this comment

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

}</pre> (no newline between } and </pre>)

* A CentralDogma based {@link EndpointGroup} implementation. This {@link EndpointGroup} retrieves the list of
* {@link Endpoint}s from a route file served by CentralDogma, and update the list when upstream data changes.
* Route file could be json file or normal text file.
* <p>
Copy link
Member

Choose a reason for hiding this comment

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

An empty <p> is redundant. Please just use an empty line.

* }
* </pre>
* <p>
* <p>The route file could be retrieve as {@link EndpointGroup} using below code:
Copy link
Member

Choose a reason for hiding this comment

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

  • retrieve -> retrieved
  • as -> as an
  • below code -> the following code


import com.linecorp.armeria.client.Endpoint;

public final class DefaultCentralDogmaJsonCodec implements EndpointListCodec<JsonNode> {
Copy link
Member

@trustin trustin Dec 14, 2017

Choose a reason for hiding this comment

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

  • How about making it package-local?
  • JsonEndpointListDecoder?


import com.linecorp.armeria.client.Endpoint;

public final class DefaultCentralDogmaTextCodec implements EndpointListCodec<String> {
Copy link
Member

@trustin trustin Dec 14, 2017

Choose a reason for hiding this comment

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

  • How about making it package-local?
  • TextEndpointListDecoder?

*
* @param <T> Type of CentralDomgma file (could be JsonNode or String)
*/
public interface EndpointListCodec<T> {
Copy link
Member

Choose a reason for hiding this comment

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

EndpointListDecoder?

public interface EndpointListCodec<T> {

/**
* Default {@link EndpointListCodec} implementation for JsonNode object.
Copy link
Member

Choose a reason for hiding this comment

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

{@link JsonNode}

public List<Endpoint> decode(String object) {
final List<String> endpoints;
try {
endpoints = OBJECT_MAPPER.readValue(object, new TypeReference<List<String>>() {});
Copy link
Member

@trustin trustin Dec 14, 2017

Choose a reason for hiding this comment

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

If an entry being watched is a JSON, decoding would be done by DefaultCentralDogmaJsonCodec. How about making this class decode a text file? e.g. a text file each line contains an endpoint:

foo.com:8080
bar.com:8443
...

Copy link
Member

@trustin trustin left a comment

Choose a reason for hiding this comment

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

Thanks!

* </ul>
* Note that the port number must be specified when you want to specify the weight.
*/
EndpointListCodec<JsonNode> DEFAULT_JSON_CODEC = new DefaultCentralDogmaJsonCodec();
Copy link
Member

Choose a reason for hiding this comment

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

JSON?

* </ul>
* Note that the port number must be specified when you want to specify the weight.
*/
EndpointListCodec<String> DEFAULT_STRING_CODEC = new DefaultCentralDogmaTextCodec();
Copy link
Member

Choose a reason for hiding this comment

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

TEXT?

import com.linecorp.armeria.client.Endpoint;

final class EndpointListCodecUtils {
static final ObjectMapper OBJECT_MAPPER = new ObjectMapper().disable(FAIL_ON_UNKNOWN_PROPERTIES);
Copy link
Member

Choose a reason for hiding this comment

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

objectMapper, because it's not really a constant?

Copy link
Member

@trustin trustin left a comment

Choose a reason for hiding this comment

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

I see a checkstyle failure:

[ERROR] C:\projects\centraldogma\client\java\src\main\java\com\linecorp\centraldogma\client\armeria\JsonEndpointListDecoder.java:19: Wrong order for 'com.linecorp.centraldogma.client.armeria.EndpointListCodecUtils.convertToEndpointList' import. [ImportOrder]

import com.linecorp.armeria.client.Endpoint;

final class TextEndpointListDecoder implements EndpointListDecoder<String> {
private static final Splitter NEWLINE_SPLITTER = Splitter.on(System.getProperty("line.separator", "\n"))
Copy link
Member

Choose a reason for hiding this comment

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

Could we make the splitter split on both \r\n and \n rather than only on one?

* <pre>{@code
* CentralDogmaEndpointGroup<JsonNode> endpointGroup = CentralDogmaEndpointGroup.ofJsonFile(
* centralDogma, "myProject", "myRepo",
* CentralDogmaCodec.DEFAULT_JSON_CODEC,
Copy link
Member

Choose a reason for hiding this comment

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

Example needs update.

@trustin trustin modified the milestones: 0.22.0, 0.23.0 Mar 8, 2018
@trustin trustin removed this from the 0.23.0 milestone Mar 30, 2018
@trustin
Copy link
Member

trustin commented Apr 16, 2018

@imasahiro Thanks for an update! Shall I review now or wait for another update?

@imasahiro
Copy link
Member Author

Maybe not ready yet. Let me update my internal usage to confirm the changes at first.

Note: Special thanks to @huydx who is the initial author of
CentralDogmaEndpointGroup(line/armeria#828)
@codecov-io
Copy link

codecov-io commented May 1, 2018

Codecov Report

Merging #105 into master will increase coverage by 0.1%.
The diff coverage is 71.73%.

Impacted file tree graph

@@            Coverage Diff            @@
##           master     #105     +/-   ##
=========================================
+ Coverage   64.47%   64.58%   +0.1%     
=========================================
  Files         271      276      +5     
  Lines        9695     9741     +46     
  Branches     1098     1099      +1     
=========================================
+ Hits         6251     6291     +40     
- Misses       2812     2818      +6     
  Partials      632      632
Impacted Files Coverage Δ
...ldogma/client/armeria/TextEndpointListDecoder.java 100% <100%> (ø)
...ntraldogma/client/armeria/EndpointListDecoder.java 100% <100%> (ø)
...ogma/client/armeria/CentralDogmaEndpointGroup.java 61.53% <61.53%> (ø)
...ldogma/client/armeria/JsonEndpointListDecoder.java 71.42% <71.42%> (ø)
...aldogma/client/armeria/EndpointListCodecUtils.java 83.33% <83.33%> (ø)
...server/internal/thrift/CentralDogmaExceptions.java 47.82% <0%> (-13.05%) ⬇️
...internal/replication/ZooKeeperCommandExecutor.java 71.94% <0%> (ø) ⬆️
... and 5 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 18a74e1...91a6fd6. Read the comment docs.

@imasahiro
Copy link
Member Author

@trustin Now ready for review.

Copy link
Member

@trustin trustin left a comment

Choose a reason for hiding this comment

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

Mostly nits. Great job!

import com.linecorp.armeria.client.Endpoint;

/**
* Decode and encode between CentralDogma upstream file content and list of {@link Endpoint}s.
Copy link
Member

Choose a reason for hiding this comment

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

Decodes the content of a file in Central Dogma into a list of {@link Endpoint}s.?

/**
* Decode and encode between CentralDogma upstream file content and list of {@link Endpoint}s.
*
* @param <T> Type of CentralDogma file (could be {@link JsonNode} or {@link String})
Copy link
Member

Choose a reason for hiding this comment

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

the type of the file in Central Dogma?

public interface EndpointListDecoder<T> {

/**
* Default {@link EndpointListDecoder} implementation for JsonNode object.
Copy link
Member

Choose a reason for hiding this comment

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

  • {@link JsonNode}
  • OK to remove 'object'?


/**
* Default {@link EndpointListDecoder} implementation for JsonNode object.
* Retrive object must be a json array (which has format as "[ \"segment1\", \"segment2\" ]"
Copy link
Member

Choose a reason for hiding this comment

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

  • Retrieve -> Retrieved
  • json -> JSON
  • ( has no matching ).

EndpointListDecoder<JsonNode> JSON = new JsonEndpointListDecoder();

/**
* Default {@link EndpointListDecoder} implementation for String object.
Copy link
Member

Choose a reason for hiding this comment

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

String object -> {@link String}?

* ]
* }</pre>
*
* <p>The route file could be retrieved as an {@link EndpointGroup} using the following code:
Copy link
Member

Choose a reason for hiding this comment

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

The JSON array file could be..

*
* <p>The route file could be retrieved as an {@link EndpointGroup} using the following code:
* <pre>{@code
* CentralDogmaEndpointGroup<JsonNode> endpointGroup = CentralDogmaEndpointGroup.of(
Copy link
Member

Choose a reason for hiding this comment

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

Could be indented one less column?

* endpointGroup.endpoints();
* }</pre>
*
* @param <T> Type of CentralDomgma file (could be {@link JsonNode} or {@link String})
Copy link
Member

Choose a reason for hiding this comment

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

the type of the file in Central Dogma?

@Test(timeout = 10000)
public void text() throws Exception {
Watcher<String> watcher = dogma.client().fileWatcher("directory", "my-service",
Query.ofText("/endpoint.txt"));
Copy link
Member

Choose a reason for hiding this comment

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

endpoints.txt?

@Test
public void json() {
Watcher<JsonNode> watcher = dogma.client().fileWatcher("directory", "my-service",
Query.ofJson("/endpoint.json"));
Copy link
Member

Choose a reason for hiding this comment

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

/endpoints.json?

@@ -0,0 +1,69 @@
/*
* Copyright 2017 LINE Corporation
Copy link
Member

Choose a reason for hiding this comment

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

2018?


/**
* Default {@link EndpointListDecoder} implementation for {@link String}.
* Retrieved object must be a string which is a list of segments separated by by a newline character.
Copy link
Member

Choose a reason for hiding this comment

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

by by?

/**
* Decodes an object into a set of {@link Endpoint}s.
*
* @param object an object retrieve from Central Dogma.
Copy link
Member

Choose a reason for hiding this comment

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

retrieved?

* centralDogma, "myProject", "myRepo",
* Query.ofJson("/endpoints.json"),
* EndpointListDecoder.JSON
* )
Copy link
Member

Choose a reason for hiding this comment

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

) -> );
You can append it after EndpointListDecoder.JSON without the newline. :)

private static final long WATCH_INITIALIZATION_TIMEOUT_MILLIS = TimeUnit.SECONDS.toMillis(10);

private final Watcher<T> instanceListWatcher;
private final EndpointListDecoder<T> endpointCodec;
Copy link
Member

Choose a reason for hiding this comment

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

I'm not sure if we need a different name for this. Codec means encoder and decoder, but this seems like only decoding now.
Is there any chance to use this as encoder later?

Copy link
Member

@minwoox minwoox left a comment

Choose a reason for hiding this comment

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

Great job!

@trustin trustin added this to the 0.25.0 milestone May 9, 2018
Copy link
Member

@trustin trustin left a comment

Choose a reason for hiding this comment

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

Just some nits. Great job!

.join();

await().atMost(10, TimeUnit.SECONDS).untilAsserted(() -> assertThat(latch.getCount()).isZero());
assertThat(endpointGroup.endpoints()).isEqualTo(ImmutableList.of(Endpoint.of("foo.bar", 1234)));
Copy link
Member

Choose a reason for hiding this comment

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

nit: Could use containsExactly()?

dogma.client().push("directory", "my-service",
Revision.HEAD, "commit",
Change.ofTextUpsert("/endpoints.txt",
"foo.bar:1234"))
Copy link
Member

Choose a reason for hiding this comment

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

nit: Could be merged into a single line


@Test(timeout = 10000)
public void text() throws Exception {
Watcher<String> watcher = dogma.client().fileWatcher("directory", "my-service",
Copy link
Member

Choose a reason for hiding this comment

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

Could use try-resources?


@Test
public void json() throws Exception {
Watcher<JsonNode> watcher = dogma.client().fileWatcher("directory", "my-service",
Copy link
Member

Choose a reason for hiding this comment

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

Could use try-resources?

Copy link
Member

@trustin trustin left a comment

Choose a reason for hiding this comment

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

Thanks, @imasahiro and @huydx!

@trustin
Copy link
Member

trustin commented May 10, 2018

@hyangtack Comments?

@trustin trustin merged commit aed4dff into line:master May 11, 2018
@trustin
Copy link
Member

trustin commented May 11, 2018

Thanks, @imasahiro, @huydx and reviewers :-)

@imasahiro imasahiro deleted the armeria branch May 11, 2018 10:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants