Skip to content

Conversation

@hiranya911
Copy link
Contributor

@hiranya911 hiranya911 commented Feb 26, 2018

We are now approaching the final phase of the thread model refactoring work we started last year (#55). So far we have deprecated the Task API and all the methods that return a Task. This PR removes those deprecated public methods, and adds a set of synchronous methods in their place. For instance FirebaseAuth will now have:

String createCustomToken(String uid) // Added in this PR
ApiFuture<String> createCustomTokenAsync(String uid) // Already exists

This is a breaking change, and hence will not be merged/released anytime soon. Instead I'll use this PR as a way to set up the v6 branch, and develop other breaking changes planned for the next major release on top it.

go/firebase-admin-java-sync

Copy link
Contributor

@schmidt-sebastian schmidt-sebastian left a comment

Choose a reason for hiding this comment

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

Have you thought of just calling the async methods directly from the synchronous methods? That would get rid of the "...Op()" methods and could drastically reduce the testing code in this PR while retaining the same test coverage.

try {
return initializeApp(getOptionsFromEnvironment(), name);
} catch (IOException e) {
throw new IllegalArgumentException("Failed to load settings from the environment", e);
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you be more descriptive here? Maybe something like 'from you system's environment variables'?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

* @return A Firebase custom token string.
* @throws IllegalArgumentException If the specified uid is null or empty, or if the app has not
* been initialized with service account credentials.
* @throws FirebaseAuthException If an error occurs while minting the custom token.
Copy link
Contributor

Choose a reason for hiding this comment

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

"retrieving" instead of minting? "Minting" seems like an internal term.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Changed to "generating"

*/
public ApiFuture<Void> setValueAsync(Object value) {
return new TaskToApiFuture<>(setValue(value));
return setValueInternal(value, PriorityUtilities.parsePriority(this.path, null), null);
Copy link
Contributor

Choose a reason for hiding this comment

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

Are we planning on either renaming these back to setValue() or on adding blocking methods?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

There are no plans to introduce blocking methods to database, since the implementation is asynchronous all the way down to the core. Developers can wait on the futures if they need blocking-like semantics.

if (TEST_FIREBASE_THREAD.equals(threadName)) {
return threadName;
}
return SAME_THREAD;
Copy link
Contributor

Choose a reason for hiding this comment

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

Should this just return the thread name? Or a boolean/enum with the result of the thread check?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

/**
* A generic operation that can be called with arbitrary arguments.
*/
public interface GenericFunction<T> {
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't see any code that uses more than one argument. If I remember correctly, this Admin SDK is also moving to Java 7. Can you then just use https://docs.oracle.com/javase/8/docs/api/java/util/function/Function.html?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

There are some multi arg function calls in FCM tests. But you're right. Once we are on java8 we should be able to clean this up significantly with native Function interface and lambdas. Specifically, I plan to replace most anonymous CallableOp instances with lambdas.

@hiranya911
Copy link
Contributor Author

hiranya911 commented Mar 1, 2018

Made the suggested changes. As for calling async methods from sync ones, we are trying to provide a stronger guarantee here than merely providing blocking semantics. We are trying to ensure that blocking methods actually execute on the calling thread, and are guaranteed to not spawn any new threads under the hood. This means developers can easily plug the SDK into thread-constrained runtimes (GAE, other J2EE containers etc) and run everything on runtime-provisioned threads if they want to.

auth.createCustomToken(uid); // Runs on the calling thread
auth.createCustomTokenAsync(uid).get(); // Runs on SDK thread pool. Just blocks the calling thread.

Copy link
Contributor

@avishalom avishalom left a comment

Choose a reason for hiding this comment

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

LGTM but a nit.

*
* @param uid The UID to store in the token. This identifies the user to other Firebase services
* (Realtime Database, Storage, etc.). Should be less than 128 characters.
* (Firebase Realtime Database, Firebase Auth, etc.).
Copy link
Contributor

Choose a reason for hiding this comment

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

Any reason to drop the length qualifier? (good either way)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added it back.

checkTopic(topic);

return ImplFirebaseTrampolines.submitCallable(app, new Callable<TopicManagementResponse>() {
private CallableOperation<String, FirebaseMessagingException> makeSendRequest(
Copy link
Contributor

@avishalom avishalom Mar 8, 2018

Choose a reason for hiding this comment

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

Could this be named sendOp to be in line with the rest of the CallableOperations names?

(and topicManagementOp , below)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good idea. Changed to sendOp and manageTopicOp

try {
return initializeApp(getOptionsFromEnvironment(), name);
} catch (IOException e) {
throw new IllegalArgumentException(
Copy link
Contributor

@avishalom avishalom Mar 8, 2018

Choose a reason for hiding this comment

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

Change javadocs to IllegalArgumentException.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

Copy link
Contributor

@avishalom avishalom Mar 8, 2018

Choose a reason for hiding this comment

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

nm

@hiranya911
Copy link
Contributor Author

DO NOT MERGE (BREAKING CHANGES)

* Removed the deprecated FirebaseCredential API

* Removing the deprecated Task API
* Dropping support for GAE 7

* Removed GaeThreadFactory, GaeExecutorService and RevivingScheduledExecutor

* Removed the deprecated FirebaseCredential API

* Removing GAE java7 related APIs (GaeThreadFactory, RevivingScheduledExecutor)

* Removed GaePlatform implementation

* Added FirebaseScheduledExecutor

* Updated documentation

* Some minor nits from code reviews

* Calling super method in DefaultRunLoop executor
* Dropping support for GAE 7

* Removed GaeThreadFactory, GaeExecutorService and RevivingScheduledExecutor

* Removed the deprecated FirebaseCredential API

* Removing GAE java7 related APIs (GaeThreadFactory, RevivingScheduledExecutor)

* Removed GaePlatform implementation

* Added FirebaseScheduledExecutor

* Updated documentation

* Removing LogWrapper API

* Removing PrefixedLogger

* Removing test config file

* Updated CHANGELOG

* Minor clean ups pointed out in the code review
@hiranya911 hiranya911 merged commit 93d0810 into master May 7, 2018
@hiranya911 hiranya911 deleted the v6 branch May 8, 2018 20:04
@dimipaun
Copy link

Hi @hiranya911, as I commented already, removing the Task based API precludes us from sharing code between Android and the Server. This is a non-trivial problem, and it completely breaks a lot of our testing harness that shares code from Android.

@hiranya911
Copy link
Contributor Author

@dimipaun This is not a use case we intend to support. FWIW, we did not intend to support it in the past either. It sort of worked that way due to the similarity in the API signatures. But we certainly don't want developers to rely on that behavior. We want the Admin SDK, and the Android SDK to evolve independently. Specifically, we want the Admin SDK to follow the conventions established by the other server-side gcloud libraries. Therefore supporting an adhoc Task API is both awkward and expensive for us.

To be honest I'm not sure how you even got the same code to work in these 2 environments. The Task interface in Android and Admin SDK belong to different packages. So at least their import statements should be different. They are really 2 different classes, that happened to have the same short name, and the same public API surface. That is not really code sharing. It is relying on the syntactic similarity between two different APIs, which is always risky.

You may have noticed that this change is now in effect in the 6.0.0 release. You can continue to use the 5.x.x versions of the SDK while you figure out a migration plan. I would highly encourage you to migrate your server-side components to use the ApiFuture interface. If syntactic similarity with Task is critical, you can try implementing your own Task wrapper around the futures (you can even try to implement the actual Task interface from Android gms, and attempt actual code sharing with compiler support).

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.

4 participants