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

Handle cyclic dependency between RCEA and Flags #4285

Merged
merged 6 commits into from Jul 4, 2022

Conversation

jrhee17
Copy link
Contributor

@jrhee17 jrhee17 commented Jun 7, 2022

Motivation:

A cyclic dependency can be introduced while RequestContextStorageProvider is being initialized.
A possible scenario is as follows:

Given that a user defined RCEA and enabled Flags logging:

  1. A user tries to call Flags#requestContextStorageProvider
  2. Before Flags#requestContextStorageProvider is fully initialized, a log is appended
    logger.info("{}: {} ({})", flagName, value, provider.name());
  3. RequestContextExportingAppender#append is invoked, which eventually calls
    final RequestContext ctx = RequestContext.currentOrNull();
  4. The above call tries to initialize a new instance of RequestContextUtil, which again calls Flags#requestContextStorageProvider. null is returned from this call which results in an error.
    final RequestContextStorageProvider provider = Flags.requestContextStorageProvider();
    try {
    requestContextStorage = provider.newStorage();
    } catch (Throwable t) {
    throw new IllegalStateException("Failed to create context storage. provider: " + provider, t);
    }

Modifications:

  • Define a FlagsLoaded class, which contains a static variable loaded representing whether Flags has been completely loaded.
  • Add a static initializer at the end of Flags which sets FlagsLoaded#loaded to true via FlagsLoaded#set.
  • Check FlagsLoaded#get from RequestContextExportingAppender and don't proceed with the appender if not ready
  • Add an isolated integration test

Result:

@codecov
Copy link

codecov bot commented Jun 7, 2022

Codecov Report

Merging #4285 (a3ed623) into master (3c61331) will increase coverage by 0.02%.
The diff coverage is 62.50%.

@@             Coverage Diff              @@
##             master    #4285      +/-   ##
============================================
+ Coverage     73.34%   73.36%   +0.02%     
- Complexity    16967    16992      +25     
============================================
  Files          1450     1451       +1     
  Lines         64055    64126      +71     
  Branches       8046     8068      +22     
============================================
+ Hits          46983    47048      +65     
- Misses        12978    12981       +3     
- Partials       4094     4097       +3     
Impacted Files Coverage Δ
...ommon/logback/RequestContextExportingAppender.java 66.66% <0.00%> (-1.97%) ⬇️
...c/main/java/com/linecorp/armeria/common/Flags.java 66.56% <100.00%> (+0.20%) ⬆️
.../linecorp/armeria/internal/common/FlagsLoaded.java 100.00% <100.00%> (ø)
...ecorp/armeria/dropwizard/ArmeriaServerFactory.java 70.27% <0.00%> (-8.07%) ⬇️
...rmeria/internal/common/kotlin/ArmeriaKotlinUtil.kt 35.29% <0.00%> (-6.38%) ⬇️
...p/armeria/common/stream/FuseableStreamMessage.java 81.36% <0.00%> (-1.87%) ⬇️
...rp/armeria/common/stream/DefaultStreamMessage.java 89.00% <0.00%> (-1.58%) ⬇️
...eria/internal/common/AbstractKeepAliveHandler.java 78.68% <0.00%> (-1.10%) ⬇️
...rmeria/internal/client/grpc/ArmeriaClientCall.java 80.73% <0.00%> (-0.41%) ⬇️
...armeria/internal/common/CancellationScheduler.java 78.17% <0.00%> (-0.40%) ⬇️
... and 23 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 3c61331...a3ed623. Read the comment docs.

@jrhee17 jrhee17 marked this pull request as ready for review June 8, 2022 02:49
@jrhee17 jrhee17 added the defect label Jun 8, 2022
@jrhee17 jrhee17 added this to the 1.17.0 milestone Jun 8, 2022
core/src/main/java/com/linecorp/armeria/common/Flags.java Outdated Show resolved Hide resolved

import org.junit.jupiter.api.Test;

public class CyclicDependencyTest {
Copy link
Contributor

Choose a reason for hiding this comment

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

How about prefixing Flags to tell what could have cyclic dependencies.

Suggested change
public class CyclicDependencyTest {
class FlagsCyclicDependencyTest {

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Forgot about this comment 😅 Will handle renaming soon

module: rcea -> flags-cyclic-dep (since I doubt other tests will be added in this module)
test class: CyclicDependencyTest -> FlagsCyclicDependencyTest
testn ame: basicCase

Comment on lines 197 to 203
if (!isInitialized()) {
return;
}

if (exporter == null) {
exporter = builder.build();
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we defer the creation of exporter until isInitialized() is true?

Copy link
Contributor

Choose a reason for hiding this comment

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

; so that isInitialized() is only invoked when exporter is null.

Copy link
Contributor Author

@jrhee17 jrhee17 Jun 8, 2022

Choose a reason for hiding this comment

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

I'm unsure if I understood your intention 😅
Doesn't the current change defer setting a value to exporter until isInitialized() == true by returning early already?
I saw your second comment late, makes sense 👍
e.g.

        if (exporter == null) {
            if (!isInitialized()) {
                return
            }
            exporter = builder.build();
        }

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.

Thanks! 👍

Copy link
Contributor

@ikhoon ikhoon left a comment

Choose a reason for hiding this comment

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

Thanks, @jrhee17!

Copy link
Contributor

@ikhoon ikhoon left a comment

Choose a reason for hiding this comment

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

Looks good with the new changes!

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 for fixing this, @jrhee17!

@trustin
Copy link
Member

trustin commented Jul 1, 2022

Please update the PR description before merging.

@jrhee17
Copy link
Contributor Author

jrhee17 commented Jul 4, 2022

Please update the PR description before merging.

Oops 😅 Updated the Modifications section to reflect recent code changes 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants