Skip to content

binder: Let servers load their SecurityPolicy asynchronously#12874

Open
jdcormie wants to merge 1 commit into
grpc:masterfrom
jdcormie:async-from-future
Open

binder: Let servers load their SecurityPolicy asynchronously#12874
jdcormie wants to merge 1 commit into
grpc:masterfrom
jdcormie:async-from-future

Conversation

@jdcormie

Copy link
Copy Markdown
Member

Android IPC servers can't defer "listening" while some slow or async initialization process completes. Instead, Android tells a server to initialize itself just-in-time for the first client connection. And this instruction arrives as a callback to Service#onCreate() then Service#onBind() on the app's main thread, where blocking to load a security policy would risk an "Application Not Responding" (ANR) error.

For demonstration of need see CL/918859271.

Android IPC servers can't defer "listening" while some slow or async
initialization process completes. Instead, Android *tells* a server to
initialize itself just-in-time for the first client connection. And this
instruction arrives as a callback to Service#onCreate() then
Service#onBind() on the app's main thread, where blocking to load a
security policy would risk an "Application Not Responding" (ANR) error.
@jdcormie

Copy link
Copy Markdown
Member Author

@groakley I can't seem to assign this to you but as creator of the existing composite security policies could you please review?

*/
@ExperimentalApi("https://github.com/grpc/grpc-java/issues/8022")
public static AsyncSecurityPolicy fromFuture(
final ListenableFuture<? extends AsyncSecurityPolicy> futurePolicy) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Our team normally writes this kind of API to accept an AsyncCallable rather than a ListenableFuture for a few reasons:

  • Defers work as long as possible. With the current signature, creating the SecurityPolicy still requires you to kick off work, even if you don't block on it. With AsyncCallable, starting that work is deferred until checkAuthorizationAsync is called. (If you are intentionally pre-warming, it's still possible to get that behavior with the AsyncCallable signature.)
  • If the work represented by the ListenableFuture can fail transiently, it will be retried the next time checkAuthorizationAsync is called and may have a chance to succeed.
  • If the work represented by the ListenableFuture can be cancelled externally, this policy gets "stuck" forever in the cancelled state.

Drawbacks:

  • If you want to avoid duplicate work, you will need the AsyncCallable you pass in to do that deduplication. There is a utility class for this.

* @param futurePolicy The future that will resolve to the delegate security policy.
*/
@ExperimentalApi("https://github.com/grpc/grpc-java/issues/8022")
public static AsyncSecurityPolicy fromFuture(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Futures.transform (and similar methods) that don't take an explicit executor are disallowed in google3. I assume Guava would have done the same in open source if that had been at all viable to change after-the-fact in external. I'd rather not introduce new methods that use that use an implicit directExecutor() for the same reasons. I'd prefer just have the other method signature that takes an Executor.

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