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

Multiple functions/endpoints per project fails with 'There is no handler configured for FUNCTION_TARGET "function"' #241

Closed
jimmyff opened this issue May 28, 2021 · 8 comments
Labels
kind/question Further information is requested

Comments

@jimmyff
Copy link

jimmyff commented May 28, 2021

Hey, I assumed I could have multiple function endpoints with a functions.dart looking something like this:

@CloudFunction()
void cloud_event(CloudEvent event, RequestContext context) {
  // ...
}

@CloudFunction()
Response simple_request(Request request) => Response.ok('Hey!');

// more cloud functions listed here...

But when my app compiles I get the error message: "There is no handler configured for FUNCTION_TARGET 'function'."

It appears in the Makefile you need to specify a function target, how does this work for projections with multiple functions?

My Makefile: (taken from one of the examples)

.PHONY: clean

FUNCTION_TARGET = function
PORT = 8080

# bin/server.dart is the generated target for lib/functions.dart
bin/server.dart:
	dart run build_runner build --delete-conflicting-outputs

build: bin/server.dart

test: clean build
	dart test

clean:
	dart run build_runner clean
	rm -rf bin/server.dart

run: build
	dart run bin/server.dart --port=$(PORT) --target=$(FUNCTION_TARGET)
@mtwichel
Copy link

mtwichel commented Jun 8, 2021

Hey @jimmyff,

I'm not the package maintainer, but I've had some time playing with it.

I don't have a lot of experience with Makefiles so I run the commands manually and the --target works well. As per this quickstart you can set environment variable FUNCTION_TARGET to your function name when starting the server and it will run that function.

As for deploying, if you're going to cloud run (for example, you could use lots of hosting options and it works the same), just set the environment variable for the service. In cloud run, when running gcloud run deploy, add --set-env-vars=[KEY=VALUE,…] (as per this doc).

As an aside, if you do use cloud run, you can point a domain with a path to cloud run using this technique. This means you can design an api with each endpoint as a cloud run service, and each cloud run service can be a CloudFunction. It's pretty slick. The only downside is for now, you have to deploy each individually. I think that would be pretty easy to solve with a .sh script though.

Hope this helps!

@jimmyff
Copy link
Author

jimmyff commented Jun 10, 2021

Thanks for the information @mtwichel

I guess I was coming from a firebase functions paradigm where you have all your functions bundled in one project. At the moment my service backend is an Aqueduct app which is hosted on Cloud Run, each endpoint is handled by the Aqueduct router.

I do think that having a cloud run service for each endpoint seems quite clumsy though. Maybe the argument for it is to do with tree-shaking and quick start up time? Hopefully the maintainers will see this and possibly have an existing solution or flag it as a future feature. 🤞

@mtwichel
Copy link

Yeah I come from that paradigm too and it's a little weird. I think under the hood Firebase cloud functions does deploy each function as it's own service, they just have a nice cli where you can deploy them all with one command.

Since you get the request object with your function I suppose you could parse the path property and run different code accordingly. I feel like that's against the idea of the functions framework, but it might still work well for your use case?

@kevmoo
Copy link
Collaborator

kevmoo commented Jun 10, 2021

CC @grant who may have reflections here...

@kevmoo kevmoo added the kind/question Further information is requested label Jun 10, 2021
@grant
Copy link
Contributor

grant commented Jun 10, 2021

The usual paradigm for multiple functions per container is to really just export 1 function (@CloudFunction() for this framework), and have that function route to other depending on the URL path (if you'd like a single deployment).

With Node, you can route request using a middleware, like this blogpost:

https://medium.com/google-cloud/express-routing-with-google-cloud-functions-36fb55885c68

Maybe there is something you can add to similarly route in the Dart function.


Generally, you want to have completely separate functions, so you can scale separately. Use Pub/Sub to connect multiple services.

@jimmyff
Copy link
Author

jimmyff commented Jun 11, 2021

Thanks for the feedback @grant, I totally see that having separate functions is the way to go in terms of deployment, I'm just wrapping my head around how I can accomplish that without create 10-15 separate projects which would be rather unwieldly.

I'll have a try at creating a dart script that will iterate over each function in my project, separately building it and deploying it as it's own cloud function. I'm sure there will be other people with similar requirements (and expectations) and I wonder if there is a way that the functions_framework package could handle this or at least make it a little easier?

Initially I assumed that I could have more than one @CloudFunction() annotation and it would just work (and it did up until deployment), it would feel very darty if it did that and each function annotation was built & deployed as a separate cloud function. It would be like the dart version of firebase functions deploy. I've no idea about the feasibility of that, but I think it would be very awesome if it worked that way.

@jimmyff
Copy link
Author

jimmyff commented Jun 17, 2021

I've basically created a controller dart cli tool which allows me to do operations across all the functions projects. I decided to go for a proper project for each function, it will be a bit annoying maintaining 10+ pubspecs when I need to update versions etc but using the controller cli tool all the testing, building & deploying simple enough. I still think that this feels a little unnecessary and would rather this just worked without all this boilerplate as per my above suggestion.

It's directory structure as follows:

functions/
  -- example_function_1/ (dart project for single function)
  -- example_function_2/
  -- example_function_3/
  -- example_function_4/
controller/ (dart cli tool for mass testing & deploying)

I did notice however that this example/test looks to support multiple functions from a single project so it looks like at some point this was the intended way it would work:
https://github.com/GoogleCloudPlatform/functions-framework-dart/blob/main/test/hello/lib/functions.dart

Anyway, I'm going to close this issue for now as it's already had a response from the team.

@diezep
Copy link

diezep commented Mar 8, 2023

I've basically created a controller dart cli tool which allows me to do operations across all the functions projects. I decided to go for a proper project for each function, it will be a bit annoying maintaining 10+ pubspecs when I need to update versions etc but using the controller cli tool all the testing, building & deploying simple enough. I still think that this feels a little unnecessary and would rather this just worked without all this boilerplate as per my above suggestion.

It's directory structure as follows:

functions/
  -- example_function_1/ (dart project for single function)
  -- example_function_2/
  -- example_function_3/
  -- example_function_4/
controller/ (dart cli tool for mass testing & deploying)

I did notice however that this example/test looks to support multiple functions from a single project so it looks like at some point this was the intended way it would work: https://github.com/GoogleCloudPlatform/functions-framework-dart/blob/main/test/hello/lib/functions.dart

Anyway, I'm going to close this issue for now as it's already had a response from the team.

@jimmyff , Do you still use this file structure or how did you manage all functions? Having a service for each function sounds somewhat redundant.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind/question Further information is requested
Projects
None yet
Development

No branches or pull requests

5 participants