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

Parse Firebase extensions from code #1590

Merged
merged 12 commits into from
Aug 16, 2024
Merged

Parse Firebase extensions from code #1590

merged 12 commits into from
Aug 16, 2024

Conversation

ifielker
Copy link
Contributor

@ifielker ifielker commented Aug 8, 2024

Parse Firebase extensions from code

@ifielker ifielker requested a review from taeold August 14, 2024 21:25
CHANGELOG.md Outdated Show resolved Hide resolved
Comment on lines +17 to +18
(cd "$f" && npm link @firebase-extensions/firebase-firestore-translate-text-sdk)
(cd "$f" && npm link @firebase-extensions/local-backfill-sdk)
Copy link
Contributor

Choose a reason for hiding this comment

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

instead of adding extensions "functions" as a test case on every single set up, can we instead separate out extensions test cases as unique ones?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

But it's the same if-else code chunk being tested... I don't want someone to "forget" to run half the tests.

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 think anybody runs this test individually but instead runs it via this test script.

I think it'd be cleaner to separate out extension use case - I see it as a specialized use case and isn't representative of most CF3 users set up.

@@ -99,14 +189,16 @@ export function mergeRequiredAPIs(requiredAPIs: ManifestRequiredAPI[]): Manifest
export async function loadStack(functionsDir: string): Promise<ManifestStack> {
const endpoints: Record<string, ManifestEndpoint> = {};
const requiredAPIs: ManifestRequiredAPI[] = [];
const extensions: Record<string, ManifestExtension> = {};
Copy link
Contributor

Choose a reason for hiding this comment

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

can extensions just be undefined if we don't have any extensions?

that feels like a safer, backward compat change (just introduce new key whenever you are defining the new extensions functions)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I tested to make sure that detectFromYaml and detectFromPort handle "extra" things by ignoring them so this change is backwards compatible as is. Technically, endpoints and extensions are at the same level. We could have extensions and no endpoints, endpoints and no extensions, or both, or neither. I'd like that to be reflected in the code. They should be handled the same way.

Copy link
Contributor

Choose a reason for hiding this comment

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

Do we think defining just the extensions as a valid use case? Not questioning whether it's technically valid - I just didn't think it's a recommended or even endorsed way to manage and deploy extensions.

Shouldn't you be using extensions manifest in your firebase.json to do that?

And this addition in Functions SDK is mainly to provide a way to easily write custom event handler as CF3 functions to extend your extensions?

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, it's a valid use case. This is not just for functions defined for extensions. It's the new way to define extensions apart from the manifest. It's useful for handling multiple similar extensions as well.
My original plan was not to involve functions code at all and have all the extensions definitions handled by extensions code, but Thomas and Michael insisted that the new extensions definitions MUST live in the functions codebase and MUST be parsed by the functions SDK. It made everything much more complicated because extensions can now be deployed using firebase deploy --only functions (so complexity x 10 as there are now multiple places to deploy extensions and they must not clobber each other etc.) Which I thought was super confusing. But Thomas insisted and said he would do "everything in his power" to prevent me from doing it any other way. So here we are :)

* @alpha
*/
export interface ManifestStack {
specVersion: "v1alpha1";
params?: WireParamSpec<any>[];
requiredAPIs: ManifestRequiredAPI[];
endpoints: Record<string, ManifestEndpoint>;
extensions: Record<string, ManifestExtension>;
Copy link
Contributor

Choose a reason for hiding this comment

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

same here - make extensions undefined-able (extensions?)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Same as above. It's already backwards compatible etc. If extensions are made undefined-able then the same should be true for endpoints... I don't want people thinking "We always have functions, but only sometimes have extensions" because it's not true

Copy link
Contributor

Choose a reason for hiding this comment

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

Understand your point, but I see extensions use case for the Functions SDK as an "extensions" to the Functions SDK, not the core experience of using the Functions SDK.

For instance, both go and dart implementation for "Firebase Functions SDK" relied on writing on the functions.yaml by hand instead. In those cases, the functions.yaml definition we defined in the Node.js served as the schema definition.

By making extensions a "required" field, we would be making these functions.yaml to add:

extensions: {}

I don't like that experience since it would be surprising to have to write extensions on their functions manifest.

(Granted, we don't really expect developers to write functions.yaml by hand, but we are talking about schema definition, and I don't think extensions should be necessary)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I agree that it's very surprising to have extensions mixed in with the functions. I made that argument strenuously and Thomas insisted that they must be. And since it must be, then we should be accurate and have extensions mixed in with the functions everywhere like he wanted. Especially since we might also support Go and dart for extensions at some point.

"_EVENT_ARC_REGION": "us-central1",
"_FUNCTION_LOCATION": "us-central1",
});
exports.extRef1 = extRef1;
Copy link
Contributor

Choose a reason for hiding this comment

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

nit* why not

exports.extRef1 = firestoreTranslateText("extRef1", {
    "COLLECTION_PATH": "collection1",
    "INPUT_FIELD_NAME": "input1",
    "LANGUAGES": "de,es",
    "OUTPUT_FIELD_NAME": "translated",
    "_EVENT_ARC_REGION": "us-central1",
    "_FUNCTION_LOCATION": "us-central1",
});

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 for the ones not referenced by functions. Also removed the extensions from the parameters test.

@ifielker ifielker merged commit 6d731d0 into master Aug 16, 2024
13 checks passed
@ifielker ifielker deleted the if-extsdk branch August 16, 2024 18:01
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