Skip to content

WIP: Add GCF samples #1506

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

Merged
merged 28 commits into from
Feb 25, 2020
Merged

WIP: Add GCF samples #1506

merged 28 commits into from
Feb 25, 2020

Conversation

ace-n
Copy link
Contributor

@ace-n ace-n commented Jul 9, 2019

DO NOT MERGE until these have been tested on Cloud Functions proper

@ace-n ace-n added the do not merge Indicates a pull request not ready for merge, due to either quality or timing. label Jul 9, 2019
@ace-n ace-n requested review from averikitsch, kurtisvg and a team July 9, 2019 23:00
@googlebot googlebot added the cla: yes This human has signed the Contributor License Agreement. label Jul 9, 2019
@kurtisvg kurtisvg self-assigned this Jul 9, 2019
@ace-n
Copy link
Contributor Author

ace-n commented Jul 9, 2019

Note: these have only been tested with Java 8, as the Java 11 runtime itself isn't ready.

Copy link
Contributor

@kurtisvg kurtisvg left a comment

Choose a reason for hiding this comment

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

There are existing samples under functions/snippets - these should be moved into that package and updated to match.

// [START functions_helloworld_gcs_event]
package com.example.functions;

public class GcsEvent {
Copy link
Contributor

Choose a reason for hiding this comment

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

This needs to use getters (and setters).

What is the point of this class?

Copy link
Contributor Author

@ace-n ace-n Jul 18, 2019

Choose a reason for hiding this comment

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

This is a struct that incoming GCS events are marshalled into.

(It's meant to be fairly read-only, so IMHO getters/setters would be overkill here.)

Copy link
Contributor

Choose a reason for hiding this comment

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

Java doesn't have have the concept of structs. It's idiomatic to use a constructor, private attributes, and getters to make it read-only.

public class HelloGcsSample {
private static Logger logger = Logger.getLogger(HelloGcsSample.class.getName());

public void helloGcs(GcsEvent event) throws Exception {
Copy link
Contributor

Choose a reason for hiding this comment

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

This doesn't match the servlet signature.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes - AFAIK, GCF itself will marshal incoming GCS notifications into this format.

Copy link
Contributor

Choose a reason for hiding this comment

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

My concern here is that Java has a very strict typing on classes, so I'm concerned that GCF isn't actually going to use a com.example.functions.GcsEvent class and this sample won't work.

Choose a reason for hiding this comment

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

We plan to have the Java GSON parser to unmarshall the GcsEvent Pojo defined along with the user function. This experience aligns with the experience we currently provide users for Go. We also plan to open source the Java functions framework at Beta, so at that point an open source event type could be considered. However, I don't think this would be something we would consider as a blocker for Beta and GA.

Copy link
Contributor

Choose a reason for hiding this comment

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

Is the class going to be derived from the parameter for the function then?

Presumably if so, it would be safe to move GcsEvent as a static class inside the class with the function. This would allow us to keep the goal of having the sample copy/pastable.

@lesv
Copy link
Contributor

lesv commented Oct 21, 2019

Status please?

@ace-n
Copy link
Contributor Author

ace-n commented Oct 21, 2019

This is on hold for now, due to product-side issues.

@ace-n
Copy link
Contributor Author

ace-n commented Jan 22, 2020

FYI: this PR is back on my radar.

I'll go through and adjust these samples to conform with the new (Java 11) GCF function signatures.

@ace-n
Copy link
Contributor Author

ace-n commented Jan 25, 2020

@kurtisvg LMK if you want me to apply your comments RE structs

cc @eamonnmcmanus


# Google Cloud Functions Java Samples

[Cloud Functions][functions_docs] is a lightweight, event-based, asynchronous
Copy link
Contributor

Choose a reason for hiding this comment

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

Do the docs have the instructions on how to run/deploy these?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not yet - I think @labtopia (TW for GCF) is working on adding them, though.

@@ -0,0 +1 @@
src/test/
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this file auto-generate?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No - but I didn't want the test code getting deployed to GCF when I use gcloud functions deploy. (Otherwise, it does unless you specifically exclude that directory in the deployment command.)

Copy link
Contributor

Choose a reason for hiding this comment

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

Could you expand on why you've chosen to do include this?

My understanding is that the Functions deployment deploys a jar? Are they compiled locally or after the code is deployed?

If it's compiled locally, I'm not sure this has any effect, and it's done remotely I'm not sure if it's a pattern we should push. As a user, if I've written tests, I want those tests to run on compile.

Copy link
Member

Choose a reason for hiding this comment

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

With GCF, you can deploy either a (self-sufficient) jar or a source hierarchy with pom.xml at the root. We expect users to deploy from source; the jar business is there to support build systems other than Maven. If you include the test source then your tests will be run remotely as part of your deployment. Whether you want that probably depends whether running them locally is enough, and on how long they take to run.

I think we should probably talk about this more in the GCF Java docs. We could also have a comment here saying what this does and why you might or might not want it. # comments are supported in .gcloudignore.

Copy link
Contributor

Choose a reason for hiding this comment

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

Since this doesn't appear to be the obvious default choice, I feel like it make the most sense to remove this for now. It seems like this this makes more sense to include in the GCF docs so the additional context makes clear it isn't required.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@kurtisvg any objection to adding a comment instead? Without this, gcloud functions deploy in the repo itself will deploy the tests by default.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think that's the behavior most people will want though right? There might be some folks that don't want to run their tests on deploy, but I don't think it should be the default action.

From my perspective as a user, I would prefer to run gcloud functions deploy and have it run the tests + deploy rather than have to run mvn verify then run gcloud functions deploy.


private LoggingClient client;

// Retrieve the latest Cloud Function log entries
public void retrieveLogs(HttpServletRequest request, HttpServletResponse response)
@Override
public void service(HttpRequest request, HttpResponse response)
throws IOException {
// Get the LoggingClient for the function.
client = getClient();
Copy link
Contributor

Choose a reason for hiding this comment

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

@kurtisvg is this idiomatic?

@averikitsch
Copy link
Contributor

Tests are failing

Copy link
Contributor

@kurtisvg kurtisvg left a comment

Choose a reason for hiding this comment

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

Please split into smaller PRs. There is too much here to easily review in a single pass.

Copy link
Member

@eamonnmcmanus eamonnmcmanus left a comment

Choose a reason for hiding this comment

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

FYI I think it would be great if we could arrange that some of these snippets were also used as the snippets that appear when you create a function in the Cloud Console. I've done some of the work for that to be possible and would be keen to do the rest. But it means that we'd probably want very skeletal snippets, and trying to make the same snippets do duty as both illustrative examples and starting points might not be the best approach.

@@ -0,0 +1,26 @@
/*
Copy link
Member

Choose a reason for hiding this comment

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

I don't think the FF should have Google-specific classes like this. However there's a good case to be made for providing another artifact that defines them, rather than having everyone reinvent them.

@kurtisvg
Copy link
Contributor

kurtisvg commented Feb 5, 2020

I just noticed that the directory organization doesn't match the normal convention (com.example.cloud.functions). @kurtisvg is this something we care about?

I think we decided that the consensus was to use com.example.*, but I don't believe we've codified it into the sample rules yet. The directory path should match the pom though.

@eamonnmcmanus
Copy link
Member

I just noticed that the directory organization doesn't match the normal convention (com.example.cloud.functions). @kurtisvg is this something we care about?

I think we decided that the consensus was to use com.example.*, but I don't believe we've codified it into the sample rules yet. The directory path should match the pom though.

I'm not sure if this is connected, but I believe at one point we only supported functions in the default package (no package declaration). That restriction no longer applies, and using the default package tends to lead to weird problems, so we should eliminate it everywhere.

Copy link
Member

@eamonnmcmanus eamonnmcmanus left a comment

Choose a reason for hiding this comment

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

I think it would make sense to submit this. It might not be perfect, but we can always fix details later.

@ace-n ace-n requested a review from kurtisvg February 18, 2020 23:23
Copy link
Contributor

@kurtisvg kurtisvg left a comment

Choose a reason for hiding this comment

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

Other outstanding issues:

  1. Java 11 tests are currently failing
  2. @averikitsch 's comment about using the correct package isn't resolved - you are still using the default package
  3. Headers still need to be updated to 2020 for new files (tried to suggest all the ones I noticed but I may have missed some - please verify)

@@ -0,0 +1 @@
src/test/
Copy link
Contributor

Choose a reason for hiding this comment

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

Could you expand on why you've chosen to do include this?

My understanding is that the Functions deployment deploys a jar? Are they compiled locally or after the code is deployed?

If it's compiled locally, I'm not sure this has any effect, and it's done remotely I'm not sure if it's a pattern we should push. As a user, if I've written tests, I want those tests to run on compile.

Copy link
Contributor

@kurtisvg kurtisvg left a comment

Choose a reason for hiding this comment

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

I think my remaining primary concerns:

  1. It looks like the classes are still in the default package (undersrc/main/java). We should really move them into a proper package to avoid any unintended weirdness.

  2. How to handle serialized events. I'm still not convinced there is a good reason to forgo best practices and skip getters and setters.

Other then those two things, I had one or two small nits.

@@ -0,0 +1 @@
src/test/
Copy link
Contributor

Choose a reason for hiding this comment

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

Since this doesn't appear to be the obvious default choice, I feel like it make the most sense to remove this for now. It seems like this this makes more sense to include in the GCF docs so the additional context makes clear it isn't required.


private EnvironmentVariables environmentVariables;

private static final TestLogHandler logHandler = new TestLogHandler();
Copy link
Contributor

Choose a reason for hiding this comment

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

Constant variables should be in all caps:

Suggested change
private static final TestLogHandler logHandler = new TestLogHandler();
private static final TestLogHandler LOG_HANDLER = new TestLogHandler();

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 throughout - marking these comments as resolved.

Copy link
Member

Choose a reason for hiding this comment

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

Actually (while we are nitting), Google Style does not say that all static final fields should be spelled with CONSTANT_CASE. Only truly immutable values should be, which TestLogHandler and Logger are not.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah interesting. I didn't know the Google Style Guide specified that - I've always just followed the traditional Java conventions where anything final is considered a constant since the reference is immutable.

@ace-n ace-n requested a review from kurtisvg February 21, 2020 21:28
Copy link
Contributor

@kurtisvg kurtisvg left a comment

Choose a reason for hiding this comment

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

LGTM once we reach a decision on the .gcloudignore

Copy link
Contributor

@kurtisvg kurtisvg left a comment

Choose a reason for hiding this comment

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

LGTM once we reach a decision on the .gcloudignore

@ace-n
Copy link
Contributor Author

ace-n commented Feb 25, 2020

FYI: I'm merging this for now, since all local tests are passing.

b/150242638 is blocking me from testing it on GCF, so I'm prepared to make changes later if issues come up.

@ace-n ace-n merged commit 30f56ef into master Feb 25, 2020
@ace-n ace-n deleted the gcf-ace branch February 25, 2020 23:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cla: yes This human has signed the Contributor License Agreement. do not merge Indicates a pull request not ready for merge, due to either quality or timing.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants