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

Bun and firestore (firebase-admin) #8549

Closed
acoyfellow opened this issue Jan 29, 2024 · 34 comments · Fixed by #14286
Closed

Bun and firestore (firebase-admin) #8549

acoyfellow opened this issue Jan 29, 2024 · 34 comments · Fixed by #14286
Labels
bug Something isn't working

Comments

@acoyfellow
Copy link

acoyfellow commented Jan 29, 2024

What version of Bun is running?

1.0.23

What platform is your computer?

Linux 5.15.0-91-generic x86_64 x86_64

What steps can reproduce the bug?

import admin from 'firebase-admin'; // 12.0.0

const {
  GCLOUD_SERVICE_ACCOUNT,
  DATABASE_URL,
  STORAGE_BUCKET
} = process.env;

admin.initializeApp({
  credential: admin.credential.cert(JSON.parse(GCLOUD_SERVICE_ACCOUNT)),
  databaseURL: DATABASE_URL,
  storageBucket: STORAGE_BUCKET,
});

const firestore = admin.firestore();

const docRef = firestore.collection('global').doc('data');

// I believe this is whats hanging when using Bun 1.0.23:
const dataDoc = await docRef.get();

const data = dataDoc.data(); // { data: { version: '0.0.0' } }

console.log({ data });

What is the expected behavior?

I expect to be able to use npm package firebase-admin, specifically firestore

What do you see instead?

No errors, just hangs.

Additional information

No response

@acoyfellow acoyfellow added the bug Something isn't working label Jan 29, 2024
@carletex
Copy link

Was about to post the same issue, but @acoyfellow did it 2 hours before. Amazing :D

Ran into the same issue. The same script runs OK with node. I have a simple script (similar to @acoyfellow's script) that hangs when trying to access the database (connection seems ok)

After a while I get:

29 | const CALL_INVOCATION_TRANSFORMER_SYMBOL = Symbol();
30 | function isFunction(arg) {
31 |     return typeof arg === 'function';
32 | }
33 | function getErrorStackString(error) {
34 |     return error.stack.split('\n').slice(1).join('\n');
                ^
TypeError: undefined is not an object (evaluating 'error.stack.split')
      at getErrorStackString (/home/**REDACTED**/node_modules/@grpc/grpc-js/build/src/client.js:34:12)
      at onReceiveStatus (/home/**REDACTED**/node_modules/@grpc/grpc-js/build/src/client.js:191:41)
      at onReceiveStatus (/home/**REDACTED**/node_modules/@grpc/grpc-js/build/src/client-interceptors.js:360:138)
      at onReceiveStatus (/home/**REDACTED**/node_modules/@grpc/grpc-js/build/src/client-interceptors.js:323:178)
      at /home/**REDACTED**/node_modules/@grpc/grpc-js/build/src/resolving-call.js:99:75

@brianmhunt
Copy link

@acoyfellow acoyfellow changed the title Bun and firestore-admin Bun and firestore (firebase-admin) Jan 29, 2024
@cirospaciari
Copy link
Member

It looks like we now get the response data into the http2 stream, but there seems to be a bug into PassThrough({ objectMode: true }) that prevent us to get the response.

@zachsents
Copy link

Any update on this? Still having problems in 1.0.29

@patrick-nurt
Copy link

Any update here? It makes it unusable for a lot of projects with this piece broken :-)

@brianmhunt
Copy link

FWIW we are just now successfully using bun to run firestore rules testing against the emulator with @firebase/rules-unit-testing. Very few issues (and we got to remove a bunch of workarounds that were needed for node/jest), relatively painless transition.

@christianbauer1
Copy link

christianbauer1 commented Mar 26, 2024

I have a similar problem but I get an error message. Using the same code in node.js without bun works without a problem. The document exists.
Using bun 1.0.35 and firebase-admin 12.0.0

When I try to get the whole collection, it only returns part of it.

  const serviceAccount = require(`./serviceAccountKey_dev.json`);
  const app = admin.initializeApp({
    credential: admin.credential.cert(serviceAccount),
  });

  const db = admin.firestore();

  const cityRef = db.collection("cities").doc("SF");
  const doc = await cityRef.get();
  if (!doc.exists) {
    console.log("No such document!");
  } else {
    console.log("Document data:", doc.data());
  }

Error:
19 | const document_1 = require("./document");
20 | const util_1 = require("./util");
21 | const logger_1 = require("./logger");
22 | /**
23 | * A wrapper around BatchGetDocumentsRequest that retries request upon stream
24 | * failure and returns ordered results.
^
error: Did not receive document for "cities/SF".

@duongdam
Copy link

duongdam commented Apr 12, 2024

now, with the latest version of bun, I get a similar error.

Ảnh màn hình 2024-04-12 lúc 16 06 08

@acoyfellow
Copy link
Author

now, with the latest version of bun, I get a similar error.

Ảnh màn hình 2024-04-12 lúc 16 06 08

I can confirm I see the same "did not recieve document for ..." error.

Firestore is a hugely popular document database, I'm very surprised this is not a higher priority for the Bun team.

Very eager to swap all of my projects (dev & prod) from Node to Bun, as this seems to be the only blocker.

@Mouvedia
Copy link

related: #9228, #9393

@Moe03
Copy link

Moe03 commented Apr 15, 2024

Hey this is still persistent for me on bun v: 1.1.3 running on windows 10

To reproduce:

$ bun add firebase-admin

then create a demo firebase project, create a firesotre database then create a collection named "users", add any sample doc, and paste the service account config then run the script.

const admin = require("firebase-admin");

export const GLOBAL_SERVICE_ACCOUNT = {
    projectId: "____",
    privateKey:
        "____",
    clientEmail: "___",
};

const app = admin.initializeApp({
    credential: admin.credential.cert(GLOBAL_SERVICE_ACCOUNT), // replace with your service account
});

export const db = app.firestore();

async function testFirestore() {
    console.log('connecting..')
    const userRef = await db.collection(`users`).limit(1).get();
    console.log(userRef.docs[0].data());
}

testFirestore()

Result successful for ts-node:

ts-node --transpileOnly bun-firebase.ts

connecting..
{
  photoURL: 'https://lh3.googleu****',
  uid: '********',
  displayName: 'Tedr****',
  joinedAt: 1707503064,
  location: '(d****',
  referredFrom: '',
  widgets: [],
  email: '*****',
  freeLTsTS: *****,
  loadTokens: *****
}

Result always undefined in bun

$ bun run bun-firebase.ts
connecting..
14 | export const db = app.firestore();
15 |
16 | async function testFirestore() {
17 |     console.log('connecting..')
18 |     const userRef = await db.collection(`users`).limit(1).get();
19 |     console.log(userRef.docs[0].data());
                     ^
TypeError: undefined is not an object (evaluating 'userRef.docs[0].data')
      at C:\Users\Mohamed\Desktop\github_repos\custom-vf-nextjs\vg-docker\bun_index.ts:19:17

@puerschel93
Copy link

Unfortunately, this is the only thing that prevents me from migrating to bun in all my backend projects. 🥲

@Moe03
Copy link

Moe03 commented Apr 19, 2024

Unfortunately, this is the only thing that prevents me from migrating to bun in all my backend projects. 🥲

Just published firebase-admin-rest: Tiny Typesafe Firebase Admin REST API wrapper that works on Vercel Edge functions, Bun, Cloudflare workers, Deno or any JS runtime.

Have already been dealing with the same problems for ages now (Bun, workers), it was crucial we use workers tho so I had to use the firebase rest api, and it wasn't fun, that package might help someone out tho :)

// firebase-admin
const db = app.firestore();
const docs = await db.collection(`users`).limit(10).get()

// firebase-admin-rest
const db = await initFirebaseRest().firestore();
const docRef = await db.doc<User>(`users`).limit(10).page(2).get(); // pagination too!

@acoyfellow
Copy link
Author

Unfortunately, this is the only thing that prevents me from migrating to bun in all my backend projects. 🥲

Just published firebase-admin-rest: Tiny Typesafe Firebase Admin REST API wrapper that works on Vercel Edge functions, Bun, Cloudflare workers, Deno or any JS runtime.

Have already been dealing with the same problems for ages now (Bun, workers), it was crucial we use workers tho so I had to use the firebase rest api, and it wasn't fun, that package might help someone out tho :)

// firebase-admin
const db = app.firestore();
const docs = await db.collection(`users`).limit(10).get()

// firebase-admin-rest
const db = await initFirebaseRest().firestore();
const docRef = await db.doc<User>(`users`).limit(10).page(2).get(); // pagination too!

this is great, thanks for the effort @Moe03. Will definitely explore using this for some projects.

@xsubject
Copy link

Confirmed. Do something about it! I want bun :(

@imMadsen
Copy link

Are there any updates on this? I've been using the "firebase-admin-rest" by Moe03, but would be awesome to be able to use the official firebase package for stability sake.

@Moe03
Copy link

Moe03 commented May 21, 2024

Are there any updates on this? I've been using the "firebase-admin-rest" by Moe03, but would be awesome to be able to use the official firebase package for stability sake.

+1 this isn't supposed to do all the functionalities of the official sdk of course and is just a temporary solution I had to create

@KatFishSnake
Copy link

+1 need this too, not sure what we can do in our monorepo with one repo of firebase functions

@bamtheboozle
Copy link

would be good to have firebase working with bun, atm we cant use bun because we don't have access to firebase auth and storage buckets :(

@AwakenedMind
Copy link

+1 gonna drop back to node for the time being...

@undesicimo
Copy link

bummer, was planning to migrate to bun

@kulterryan
Copy link

Getting error when trying to build the server with index.ts

Screenshot 2024-06-18 at 8 38 57 PM

@Gorthog
Copy link

Gorthog commented Jul 28, 2024

This works fine for me. using bun 1.1.20

import { initializeApp, type App } from 'firebase-admin/app';
import { getFirestore, Timestamp } from 'firebase-admin/firestore';

class FirebaseService {
  app: App;
  db: FirebaseFirestore.Firestore;
  constructor() {
    this.app = initializeApp();
    this.db = getFirestore(this.app);
  }

  async writeDocument(collectionName: string, documentName: string, data: any, ttl?: number) {
    try {
      if (ttl) {
        const ttlDate = new Date();
        ttlDate.setSeconds(ttlDate.getSeconds() + ttl);
        data.expiry = Timestamp.fromDate(ttlDate);
      }
      await this.db.collection(collectionName).doc(documentName).set(data);
    } catch (error) {
      console.error('Error writing document: ', error);
    }
  }

  async readDocument<T>(collectionName: string, documentName: string) {
    try {
      const docRef = this.db.collection(collectionName).doc(documentName);
      const docSnap = await docRef.get();

      if (docSnap.exists) {
        return docSnap.data() as T;
      } else {
        return null;
      }
    } catch (error) {
      console.error('Error reading document: ', error);
      return null;
    }
  }
}

export default new FirebaseService();

@JZubero
Copy link

JZubero commented Jul 30, 2024

Anyone else experiencing the random number of records are fetched in bun runtime issue?

Other than that, bun (v.1.1.21)<-->firebase is working fine for us. We are using Auth and Firestore at the moment.

@JZubero
Copy link

JZubero commented Sep 16, 2024

The Firebase team decided not to investigate the issue so my sincere hope is that the Bun team will get to the bottom of the problem with gRPC.

@brianmhunt
Copy link

Noting the potential workaround, to prefer the REST API and avoid GAX, might help here.

const db = initializeFirestore(firebaseApp, { preferRest: true });

@JZubero
Copy link

JZubero commented Sep 27, 2024

@brianmhunt Yes, fair enough, thank you for mentioning. We have started to experiment with the workaround and so far it's working well. Did you already give it a try?

@JustinBeck
Copy link

Same issue - huge blocker, but... the workaround to use Rest API seems to be holding up still.

@brianmhunt
Copy link

@JZubero unfortunately we are continuing to experience problems. We consistently see this species.

Image

> bun pm ls | grep -i fire
├── [email protected]
├── [email protected]
├── [email protected]

Bun also performs considerably worse, with an action in Node.js taking 14s on average, the equivalent bun is 22s.

We have also noticed that bun sometimes returns incorrect data from Firestore.

So there are three outstanding problems:

  1. random exceptions that cause the process to exit
  2. its slower than node.js
  3. data integrity - it's not returning what's in the datastore

@Jarred-Sumner
Copy link
Collaborator

Jarred-Sumner commented Oct 9, 2024

@cirospaciari is very actively working on improving the node:http2 implementation in Bun (which firestore and firebase use) to both be faster, pass more of Node.js’ test suite, and also support http2 server (instead of just the client)

Sorry this isn’t good yet, but we will make it good

@JZubero
Copy link

JZubero commented Oct 10, 2024

@brianmhunt Uh, that's not pretty. Thanks for keeping us posted about this. I will share our future findings regarding this here.

@Jarred-Sumner Thank you for letting us know. Could you maybe provide a rough ETA when this might land? Not wanna be pushy here, just for our internal planning 🙏

@Jarred-Sumner
Copy link
Collaborator

The fix for this will be part of the Bun v1.1.31 release

@undesicimo
Copy link

@Jarred-Sumner Thank you for the great work!

@brianmhunt
Copy link

Can confirm that Firebase Firestore now appears to have functional parity.

Our motivation to use bun isn't performance, we're mostly interested in the builtin transpilation, error traces, trajectory of the project, etc. That said I'll note that bun is slower for the use case I was testing above (reading many Firestore docs). Some benchmarks running the same code:

node: 421215ms
bun: 743336ms

The performance delta is consistently proportional to the number of Firestore docs, so at large enough scale the compilation overhead becomes insignificant.

@Jarred-Sumner FYI ^^ If the reproduction or cause of this is not apparent let me know and I can share more details. For us, it's not a priority, but please tag if it's of interest.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.