Skip to content

Functions rewrite in C##1400

Open
AustinBenoit wants to merge 15 commits intomainfrom
functionsrewrite
Open

Functions rewrite in C##1400
AustinBenoit wants to merge 15 commits intomainfrom
functionsrewrite

Conversation

@AustinBenoit
Copy link
Contributor

Description

Provide details of the change, and generalize the change in the PR title above.

Functions rewrite in C# with the goal of making this a non breaking change.

There is a couple of quirks with the reimplementation. In the previous iteration we used the C++ Variant object class that would do some type conversion. Now I have attempt to rewrite these type conversion in C#. This is just a bit odd as technically we are sending all ints as longs to the firebase functions. This is consistent with the previous implementation just a bit odd.

The second quirk is the how the bearer token is expected to be handled between AI logic and Functions. So we need to pipe through this specific name in each product.


Testing

Describe how you've tested these changes.

Ran both the functions and AI test locally in unity.


Type of Change

Place an x the applicable box:

  • Bug fix. Add the issue # below if applicable.
  • New feature. A non-breaking change which adds functionality.
  • Other, such as a build process or documentation change.

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @AustinBenoit, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly refactors the Firebase Functions client library by migrating its core logic from C++ SWIG bindings to a pure C# implementation. This change streamlines the codebase, reduces external dependencies, and provides more direct control over HTTP request handling and data serialization within the C# environment. It also introduces new internal helper classes for HTTP operations and error parsing, ensuring a robust and consistent experience for developers while maintaining backward compatibility.

Highlights

  • Functions Rewrite to C#: The Firebase Functions implementation has been completely rewritten in C#, removing the dependency on the internal C++ Variant object class and SWIG bindings. This change aims to be non-breaking.
  • Type Conversion Handling: Type conversions, previously handled by the C++ Variant object, are now explicitly managed in C#. All integers are consistently sent as longs to Firebase Functions, mirroring the previous behavior.
  • Authentication Token Management: The handling of bearer tokens between AI logic and Functions has been refined, introducing a customizable authentication token prefix to ensure proper piping of specific names across products.
  • Build System Updates: The CMake build system and Unity package exports have been updated to reflect the removal of C++ dependencies for Functions, now packaging C# source files directly and adjusting plugin imports.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • CMakeLists.txt
    • Removed references to firebase_functions_swig and firebase_functions libraries.
  • app/CMakeLists.txt
    • Added packing of internal C# files from app/src/internal/ as raw source.
  • app/src/internal/HttpHelpers.cs
    • Added new helper class HttpHelpers for setting common HTTP request headers and adding Firebase tokens.
    • Added ValidateHttpResponse to provide detailed error information for failed HTTP requests.
    • Added HttpRequestExceptionExtensions to retrieve HTTP status codes from exceptions.
  • cmake/project.template
    • Added LangVersion property to the C# project template.
  • cmake/unity_mono.cmake
    • Added LANG_VERSION argument to mono_add_internal macro.
    • Set a default C# language version of 9.0.
  • docs/readme.md
    • Added a changelog entry for the upcoming release, noting the Functions serialization logic rewrite.
  • firebaseai/src/GenerativeModel.cs
    • Updated calls to HttpHelpers.GetURL, HttpHelpers.SetRequestHeaders, and HttpHelpers.ValidateHttpResponse to use the new Firebase.HttpHelpers class and Firebase.AI.Internal.HttpHelpers for URL generation.
  • firebaseai/src/Imagen/ImagenModel.cs
    • Updated calls to HttpHelpers.GetURL, HttpHelpers.SetRequestHeaders, and HttpHelpers.ValidateHttpResponse to use the new Firebase.HttpHelpers class and Firebase.AI.Internal.HttpHelpers for URL generation.
  • firebaseai/src/Internal/FirebaseInterops.cs
    • Renamed to app/src/internal/FirebaseInterops.cs.
    • Changed namespace from Firebase.AI.Internal to Firebase.
    • Modified AddFirebaseTokensAsync methods to accept an authTokenPrefix parameter for customizable authentication header prefixes.
  • firebaseai/src/Internal/HttpHelpers.cs
    • Removed SetRequestHeaders and HttpRequestExceptionExtensions as they were moved to app/src/internal/HttpHelpers.cs.
  • firebaseai/src/TemplateGenerativeModel.cs
    • Updated calls to HttpHelpers.GetTemplateURL, HttpHelpers.SetRequestHeaders, and HttpHelpers.ValidateHttpResponse to use the new Firebase.HttpHelpers class and Firebase.AI.Internal.HttpHelpers for URL generation.
  • functions/CMakeLists.txt
    • Rewrote the CMake configuration for Firebase Functions to package C# source files directly.
    • Removed firebase_functions_swig and firebase_functions_cs targets.
  • functions/src/FirebaseFunctions.cs
    • Rewrote the FirebaseFunctions class to remove dependency on FirebaseFunctionsInternal (SWIG-generated C++ proxy).
    • Changed instance management from Dictionary to ConcurrentDictionary (_instances).
    • Modified Dispose and OnAppDisposed to use reflection for removing event handlers.
    • Updated GetInstance methods to create and manage FirebaseFunctions instances directly.
    • Implemented GetUrl to construct function URLs based on project ID, region, and emulator origin.
    • Updated GetHttpsCallable, GetHttpsCallableFromURL, and UseFunctionsEmulator to operate directly without the C++ proxy.
  • functions/src/FunctionsException.cs
    • Modified FunctionsException constructor to accept FunctionsErrorCode and message directly.
    • Added a FunctionsErrorCode enum with various HTTP-related error codes.
  • functions/src/HttpsCallableReference.cs
    • Rewrote HttpsCallableReference to use HttpClient for making HTTP requests directly, removing dependency on HttpsCallableReferenceInternal (SWIG-generated C++ proxy).
    • Implemented MakeFunctionsRequest for serializing data and InternalCallAsync for handling the HTTP call, including setting headers and error parsing.
    • Explicitly set the authentication token prefix to "Bearer" for Functions calls.
  • functions/src/HttpsCallableResult.cs
    • Minor namespace and class declaration formatting changes.
  • functions/src/Internal/FunctionsErrorParser.cs
    • Added new helper class for mapping HTTP status codes and JSON error responses to FunctionsErrorCode and extracting error messages.
  • functions/src/Internal/FunctionsSerializer.cs
    • Added new helper class for serializing and deserializing data for Firebase Functions calls.
    • Implemented handling of proto3 wrappers for Int64Value and BytesValue.
    • Encodes all integers as Int64Value for consistency with the legacy C++ implementation.
  • functions/src/swig/functions.i
    • Removed this file, indicating the removal of SWIG C++ bindings for Firebase Functions.
  • unity_packer/exports.json
    • Added Firebase/FirebaseApp/Internal/ to be packed by DefaultImporter.
    • Removed all PluginImporter entries related to Firebase.Functions.dll, FirebaseCppFunctions.a, and FirebaseCppFunctions*.
    • Added Firebase/FirebaseFunctions/* to be packed by DefaultImporter.
Activity
  • The author ran both the functions and AI tests locally in Unity to verify the changes.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

The rewrite of Firebase Functions in C# significantly improves maintainability by removing the C++ dependency. The implementation correctly handles the core protocol and serialization. However, there are technical concerns regarding resource management and code quality. Specifically, HttpClient should be shared at the service level to avoid socket exhaustion, and the reflection-based event subscription in FirebaseFunctions is fragile and potentially leaks memory. Additionally, several 'TODO' comments should be resolved, and CancellationToken support should be added to the public API to align with modern .NET practices.

@AustinBenoit
Copy link
Contributor Author

/gemini review

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request is a significant and welcome rewrite of the Firebase Functions SDK, moving it from a C++/SWIG implementation to a pure C# implementation. This removes a native dependency and simplifies the build process, as reflected in the CMakeLists.txt changes. The refactoring also includes moving shared utilities like HttpHelpers and FirebaseInterops to a common app/src/internal location, which is a good improvement for code sharing across Firebase products.

My review has identified a few critical issues:

  • A memory leak in FirebaseFunctions.cs due to incorrect event handler disposal.
  • A syntax error in FunctionsException.cs that will break compilation.

I've also included some suggestions to improve maintainability regarding the use of reflection and to clean up leftover debug code. Overall, this is a great direction for the SDK.

@AustinBenoit AustinBenoit force-pushed the functionsrewrite branch 4 times, most recently from 0cb7d97 to 9ed1eb4 Compare February 27, 2026 23:15
@AustinBenoit
Copy link
Contributor Author

/gemini review

@AustinBenoit AustinBenoit added the tests-requested: quick Trigger a quick set of integration tests. label Feb 28, 2026
Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request is a significant and valuable rewrite of the Firebase Functions implementation, moving from a C++/SWIG wrapper to a pure C# implementation using HttpClient. This greatly improves maintainability and portability. The new implementation of serialization and error parsing seems correct. However, I've found a few critical issues that need to be addressed: a memory leak due to incorrect event handler removal, and a race condition in instance management. I've also pointed out a couple of minor issues like a leftover debug log and some unused using statements.

@github-actions github-actions bot added tests: in-progress This PR's integration tests are in progress. and removed tests-requested: quick Trigger a quick set of integration tests. labels Feb 28, 2026
@github-actions
Copy link

github-actions bot commented Feb 28, 2026

❌  Integration test FAILED

Requested by @firebase-workflow-trigger[bot] on commit 7148241
Last updated: Mon Mar 2 10:58 PST 2026
View integration test log & download artifacts

Failures Configs
missing_log [TEST] [ERROR] [2021] [1/2 Build OS(s): windows] [1/5 Platform(s): Playmode] [1/2 Test Device(s): github_runner]
functions [TEST] [FAILURE] [2021] [1/2 Build OS(s): macos] [1/5 Platform(s): 14] [1/2 Test Device(s): iOS]

@github-actions github-actions bot added the tests: failed This PR's integration tests failed. label Feb 28, 2026
@firebase-workflow-trigger firebase-workflow-trigger bot removed the tests: in-progress This PR's integration tests are in progress. label Feb 28, 2026
@AustinBenoit
Copy link
Contributor Author

/gemini review

@AustinBenoit AustinBenoit added tests-requested: quick Trigger a quick set of integration tests. and removed tests: failed This PR's integration tests failed. labels Mar 2, 2026
Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request significantly refactors the Firebase Functions implementation in C#, moving away from the C++ SWIG bindings to a pure C# approach. This change involves a complete rewrite of the FirebaseFunctions and HttpsCallableReference classes, along with the introduction of new internal serialization and error parsing utilities. The build system has also been updated to reflect this change, removing native library dependencies and packaging C# source files directly. Additionally, a configurable authentication token prefix has been introduced for greater flexibility in handling Firebase tokens.

Overall, the changes represent a substantial improvement in maintainability and potentially performance by removing the C++ interop layer. However, there are a few areas that could be improved to enhance robustness and clarity.

Comment on lines 115 to +123
private void Dispose() {
System.GC.SuppressFinalize(this);
lock (functionsByInstanceKey) {
if (functionsInternal == null) return;
functionsByInstanceKey.Remove(instanceKey);

functionsInternal.Dispose();
functionsInternal = null;

firebaseApp.AppDisposed -= OnAppDisposed;
_instances.TryRemove(_instanceKey, out _);
if (_appDisposedEvent != null && _onAppDisposedHandler != null) {
var removeMethod = _appDisposedEvent.GetRemoveMethod(true);
removeMethod?.Invoke(_firebaseApp, new object[] { _onAppDisposedHandler });
}
_httpClient.Dispose();
Copy link
Contributor

Choose a reason for hiding this comment

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

high

The Dispose method does not fully implement the IDisposable pattern. If Dispose() is called multiple times, it could lead to an ObjectDisposedException when trying to dispose _httpClient again. Consider adding a _disposed flag to ensure resources are only released once.

    private bool _disposed = false;
    private void Dispose() {
      if (_disposed) return;
      System.GC.SuppressFinalize(this);

      _instances.TryRemove(_instanceKey, out _);
      if (_appDisposedEvent != null && _onAppDisposedHandler != null) {
        var removeMethod = _appDisposedEvent.GetRemoveMethod(true);
        removeMethod?.Invoke(_firebaseApp, new object[] { _onAppDisposedHandler });
      }
      _httpClient.Dispose();
      _disposed = true;
    }

_instanceKey = InstanceKey(app, region);

// Default timeout is 70 seconds matching native SDKs.
_httpClient = new HttpClient();
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The value 70 for the HttpClient timeout is a magic number. It would be more maintainable and readable to define this as a named constant, allowing for easier modification and understanding of its purpose.

      private const int DefaultHttpClientTimeoutSeconds = 70;
      _httpClient = new HttpClient();
      _httpClient.Timeout = TimeSpan.FromSeconds(DefaultHttpClientTimeoutSeconds);

#if FIREBASE_LOG_REST_CALLS
UnityEngine.Debug.Log("Request:\n" + request.Content);
#endif
// TODO pipe through cancellation tokens
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The TODO comment indicates that cancellation tokens should be piped through. Implementing this would improve the responsiveness and resource management of asynchronous operations, especially in scenarios where long-running function calls might need to be aborted.

@AustinBenoit AustinBenoit requested a review from a-maurice March 2, 2026 16:18
@github-actions github-actions bot added tests: in-progress This PR's integration tests are in progress. and removed tests-requested: quick Trigger a quick set of integration tests. labels Mar 2, 2026
@github-actions github-actions bot added the tests: failed This PR's integration tests failed. label Mar 2, 2026
@firebase-workflow-trigger firebase-workflow-trigger bot removed the tests: in-progress This PR's integration tests are in progress. label Mar 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

tests: failed This PR's integration tests failed.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant