-
Notifications
You must be signed in to change notification settings - Fork 275
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
Implement helixAccountService with version history and blobs #1234
Conversation
Codecov Report
@@ Coverage Diff @@
## master #1234 +/- ##
============================================
- Coverage 88.92% 85.84% -3.08%
- Complexity 60 76 +16
============================================
Files 6 9 +3
Lines 352 544 +192
Branches 37 56 +19
============================================
+ Hits 313 467 +154
- Misses 29 58 +29
- Partials 10 19 +9
Continue to review full report at Codecov.
|
ambry-account/src/main/java/com/github/ambry/account/HelixAccountService.java
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Left a few initial comments. I will re-review after HelixAccountService is refactored.
ambry-account/src/main/java/com/github/ambry/account/HelixAccountService.java
Outdated
Show resolved
Hide resolved
ambry-account/src/test/java/com/github/ambry/account/HelixAccountServiceTest.java
Outdated
Show resolved
Hide resolved
ambry-account/src/main/java/com/github/ambry/account/AccountMetadataStore.java
Outdated
Show resolved
Hide resolved
ambry-account/src/main/java/com/github/ambry/account/RouterStore.java
Outdated
Show resolved
Hide resolved
ambry-account/src/main/java/com/github/ambry/account/RouterStore.java
Outdated
Show resolved
Hide resolved
ambry-account/src/main/java/com/github/ambry/account/HelixAccountService.java
Outdated
Show resolved
Hide resolved
ambry-account/src/main/java/com/github/ambry/account/RouterStore.java
Outdated
Show resolved
Hide resolved
ambry-account/src/main/java/com/github/ambry/account/RouterStore.java
Outdated
Show resolved
Hide resolved
ambry-account/src/main/java/com/github/ambry/account/RouterStore.java
Outdated
Show resolved
Hide resolved
ambry-account/src/main/java/com/github/ambry/account/RouterStore.java
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
updated
dc5ec93
to
5e4ddcb
Compare
ambry-account/src/main/java/com/github/ambry/account/AccountMetadataStore.java
Outdated
Show resolved
Hide resolved
ambry-account/src/main/java/com/github/ambry/account/AccountMetadataStore.java
Show resolved
Hide resolved
ambry-account/src/main/java/com/github/ambry/account/HelixAccountService.java
Outdated
Show resolved
Hide resolved
5e4ddcb
to
d0efbc4
Compare
Implement helixAccountService with version history Add tests Before changing the router store Add more test
dce6bd2
to
bd5b99c
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some comments. Need to take a look at tests.
ambry-account/src/main/java/com/github/ambry/account/AccountMetadataStore.java
Outdated
Show resolved
Hide resolved
ambry-account/src/main/java/com/github/ambry/account/LegacyMetadataStore.java
Outdated
Show resolved
Hide resolved
ambry-api/src/main/java/com.github.ambry/config/HelixAccountServiceConfig.java
Outdated
Show resolved
Hide resolved
if (notifier != null) { | ||
notifier.subscribe(ACCOUNT_METADATA_CHANGE_TOPIC, changeTopicListener); | ||
} else { | ||
logger.warn("Notifier is null. Account updates cannot be notified to other entities. Local account cache may not " | ||
+ "be in sync with remote account data."); | ||
accountServiceMetrics.nullNotifierCount.inc(); | ||
} | ||
if (config.useNewZNodePath) { | ||
accountMetadataStore = new RouterStore(this.accountServiceMetrics, backup, helixStore, router); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I understand this is first PR to improve account metadata and I believe setupRouter
will be invoked in future PR, however, here router
might not be initialized, can we do some proactive check in RouterStore
?
Eventually, after transition is done, we should explicitly call setupRouter
in RestServer.java
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good idea, updated
* @param isCalledFromListener True is this function is invoked in the {@link TopicListener}. | ||
*/ | ||
private synchronized void fetchAndUpdateCache(boolean isCalledFromListener) { | ||
Map<String, String> accountMap = accountMetadataStore.fetchAccountMetadata(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Although this is synchronized
method, there might be race condition when initialFetchAndSchedule
is called before accountMetadataStore
is instantiated. My suggestion is, if possible, move notifier.subscribe()
to the end of constructor.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good Idea, I move the notifier.subscribe into the initialFetchAndSchedule function so there will be no race condition here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good after minor comments are addressed.
ZNRecord znRecord = helixStore.get(znRecordPath, null, AccessOption.PERSISTENT); | ||
logger.trace("Fetched ZNRecord from path={}, took time={} ms", znRecordPath, startTimeMs); | ||
if (znRecord == null) { | ||
logger.debug("The ZNRecord to read does not exist on path={}", znRecordPath); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
minor: I think here can be warn
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
but it's not a warning message. ZNRecord can be null here. It's one of the legit state.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If not warn
, I would suggest info
because such info is supposed to be printed out (debug
level is turned off by default). I feel like ZNRecord should exist in almost all cases, if not, it's actually a warning that either the ZNode is deleted or znRecordPath is incorrect.
} | ||
List<String> accountBlobIDs = record.getListField(ACCOUNT_METADATA_BLOB_IDS_LIST_KEY); | ||
if (accountBlobIDs == null || accountBlobIDs.size() == 0) { | ||
logger.debug("ZNRecord={} to read on path={} does not have a simple list with key={}", record, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same here, maybe use warn
?
throw new IllegalStateException(errorMessage, e); | ||
} catch (Exception e) { | ||
errorMessage = | ||
String.format("Unexpected exception occurred when parsing the blob id list from {}", accountBlobIDs); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if you choose to String.format, can you change it to following style (basically replace {}
with %s
):
String.format("Unexpected exception occurred when parsing the blob id list from %s", accountBlobIDs);
Make change to all occurrences. This can pass intellij inspection.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
figured that string concatenation would just do the work.
This is the first step of implementation for this design https://docs.google.com/document/d/1Lr30Uph1KL0AMHznTGEdC_JG3W6_d_NKNTa9FbBTTjI/edit
In this implementation, HelixAccountService has two separated implementation of AccountMetadataStore, which fetches account metadata and update it.
Old approach is still the default implementation and new approach would be enabled after.
The next step is to
Notice that this implementation might end up with some blob leak.