Dart Functions Framework usage

272 Views Asked by At

I'm new to the Dart functions framework. My goal is to use this package to create several functions and deploy them to Cloud Run (in combination with Firebase, but I guess that's irrelevant to this question).

I've run the quick starts and I've read all of the contents in the docs.

The quick start mentions just one function at a time (e.g. Hello World, Cloud Events, etc..), like this:

import 'package:functions_framework/functions_framework.dart';
import 'package:shelf/shelf.dart';

@CloudFunction()
Response function(Request request) {
    return Response.ok('Hello, World!');
}

But as you can see in the quickstarts only one function is handled in a project at a time. How about me wanting to deploy several functions? Should I:

  1. Write several functions in the same project / file, so that the function framework compiles the 'server.dart` by itself

OR

  1. Create a different functions_framework for each function?

Let me be more specific. Should I do the following (option 1 - which makes more sense to me):

import 'dart:math';

import 'package:functions_framework/functions_framework.dart';
import 'package:shelf/shelf.dart';

@CloudFunction()
Response function(Request request) {
    return Response.ok('Hello, World!');
}

@CloudFunction()
Response function2(Request request) {
  if (Random().nextBool()) {
    return Response.ok('Hello, World!');
  } else {
    return Response.internalServerError();
  }
}

Or should I build a different folder by running a build_runner for each function I need in my project?

Is there a difference and/or a best practice? Thanks in advance.

EDIT. This question is related to the deployment on Cloud Run itself, and not just testing on my own PC. To test my own functions I did the following:

  1. Run dart run build_runner build, so that it updates the server.dart file correctly (I can see that the framework does a lot behind the scenes and that the _nameToFunctionTarget is basically a router);
  2. Run the server in two different terminals, like this: dart run bin/server.dart --port MYPORT --target MYFUNCTION (where MYPORT and MYFUNCTION are either 8080/8081 or function/function2 respectively).

I guess I'm just confused on how to correctly manage this framework once deployed on Cloud Run.

EDIT 2. I just gave up using Dart as a Serverless language or even a Backend language. There's just too much jargon even for the basic things. Any backend framework is either dead, or maintained by one single enthusiast guy (props to him!). This language has not yet received enough love from the Google Team / the community and at this moment in time is basically not possible to go fullstack on just Dart. It's a dream, but it can't be realized now. Furthermore, Dart hardly lacks a proper SDKs to use Firestore, etc., so Firebase isn't an option. I find it easier to just learn NodeJS and exploit the Firebase support for Firebase Functions written in NodeJS, and I'll wait for more support in there in the future, if there ever will be.

1

There are 1 best solutions below

0
On

The documentation is a bit sparse right now (and I'm new to it also! I couldn't find any good examples, so here goes...)

  • You can only have a single function that is served. It should be named 'function' (the type and name can be overriden, see the cloudevent example dartfn generate cloudevent)
  • You 'could' have many of these deployed so that each does a specific thing, such as processing cloudevents above, but most people want something more REST-like (see next)
  • You need to attach a Router() so that you can have the single entry point (function) handled by specific logic in your code.

Example for Rest

  1. add to pubspec.yaml (in dependencies:) shelf_router: ^1.1.2
  2. delegate the @CloudFunction to use the Router()

functions.dart

import 'package:functions_framework/functions_framework.dart';
import 'package:shelf/shelf.dart';
import 'package:shelf_router/shelf_router.dart';

Router app = Router()
  ..get('/health', (Request request) {
    return Response.ok('healthy');
  })
  ..get('/user/<user>', (Request request, String user) {
    // fetch the user... (probably return as json)
    return Response.ok('hello $user');
  })
  ..post('/user', (Request request) {
    // convert request body to json and persist... (probably return as json)
    return Response.ok('saved the user');
  });

@CloudFunction()
Future<Response> function(Request request) => app.call(request);