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

Firestore not working offline as expected | setDoc not updating local cache when offline #8696

Open
vishwa795 opened this issue Jan 9, 2025 · 8 comments

Comments

@vishwa795
Copy link

vishwa795 commented Jan 9, 2025

Operating System

macOS Sonoma (14.4.1)

Environment (if applicable)

Chrome 131.0.6778.205

Firebase SDK Version

11.0.2

Firebase SDK Product(s)

Firestore

Project Tooling

React app with Webpack

Detailed Problem Description

What I am trying to achieve?

Ability to add documents / update documents while the device is offline.

What actually happened?

Functions like setDoc do not resolve indefinitely until internet is available, which seems like the expected behaviour.

However it's mentioned in docs that when persistance is enabled, firestore will update it's local cache first and trigger a onSnapshot callback (with fromCache and hasPendingWrites true given that includeMetadataChanges is marked true), which doesn't seem to be happening.

Error / Unexpected behaviour

Firestore not updating local cache and not triggering onSnapshot when multi-tab persistance is enabled.

Relevant log snippets or console output

Pasting the debug logs from firestore that I see on browser console, when i go offline, and perform a setDoc operation.

[2025-01-09T07:33:18.212Z]  @firebase/firestore: Firestore (11.0.2): IndexedDbPersistence Starting transaction: updateClientMetadataAndTryBecomePrimary
main.6b4c4e61.js:2 [2025-01-09T07:33:18.213Z]  @firebase/firestore: Firestore (11.0.2): SharedClientState SET firestore_sequence_number_firestore/[DEFAULT]/eka-care-preprod.doctool/ 8736
main.6b4c4e61.js:2 [2025-01-09T07:33:18.213Z]  @firebase/firestore: Firestore (11.0.2): SimpleDb GET owner owner {"ownerId":"zPkMnyOxyJ08NL9MeOHr","allowTabSynchronization":true,"leaseTimestampMs":1736407994210}
main.6b4c4e61.js:2 [2025-01-09T07:33:18.213Z]  @firebase/firestore: Firestore (11.0.2): IndexedDbPersistence Client 'zPkMnyOxyJ08NL9MeOHr' is not zombied in LocalStorage
main.6b4c4e61.js:2 [2025-01-09T07:33:18.213Z]  @firebase/firestore: Firestore (11.0.2): SimpleDb PUT clientMetadata <auto-key> {"clientId":"zPkMnyOxyJ08NL9MeOHr","updateTimeMs":1736407998213,"networkEnabled":true,"inForeground":true}
2main.6b4c4e61.js:2 [2025-01-09T07:33:18.214Z]  @firebase/firestore: Firestore (11.0.2): SimpleDb GET owner owner {"ownerId":"zPkMnyOxyJ08NL9MeOHr","allowTabSynchronization":true,"leaseTimestampMs":1736407994210}
main.6b4c4e61.js:2 [2025-01-09T07:33:18.214Z]  @firebase/firestore: Firestore (11.0.2): IndexedDbPersistence Client 'zPkMnyOxyJ08NL9MeOHr' is not zombied in LocalStorage
main.6b4c4e61.js:2 [2025-01-09T07:33:18.214Z]  @firebase/firestore: Firestore (11.0.2): SimpleDb PUT owner owner {"ownerId":"zPkMnyOxyJ08NL9MeOHr","allowTabSynchronization":true,"leaseTimestampMs":1736407998214}

The above set of logs repeat multiple times in my browser console.

Steps and code to reproduce issue

Firestore Setup

const app = initializeApp(FIREBASE_CONFIG);
const auth = getAuth(app);
setLogLevel('debug');

const FIVE_MB_IN_BYTES = 5000000;

const firestore = initializeFirestore(
    app,
    {
        ignoreUndefinedProperties: true,
        localCache: persistentLocalCache(
            {
                tabManager: persistentMultipleTabManager(),
                cacheSizeBytes: FIVE_MB_IN_BYTES,
            },
        ),
    },
    FIRESTORE_DB_NAME,
);

onSnapshot setup

export default async function setupSnapshotListener({
    queries
    onSnapshot,
    onError,
}: {
    queries: QueryConstraint[];
    onSnapshot?: (snapshot: QuerySnapshot<DocumentData, DocumentData>) => void;
    onError?: (error: FirestoreError) => void;
}): Promise<Unsubscribe> {
    const snapshotQuery = query(collection(firestore, COLLECTION_NAME.TEST), ...queries);

    return onSnapshot(
        snapshotQuery,
        { includeMetadataChanges: true },
        (snapshot) => {
            onSnapshot(snapshot);
        },
        (error) => {
            console.log('Error in apt snapshot', error);
            onError?.(error);
        },
        () => {
            console.log('Snapshot listener completed');
        },
    );
}

Update Document

export async function updateDocument({
    docId,
    data,
}: {
    docId: string;
    data: any;
}): Promise<unknown> {
    const updates = {
        ...data,
        updated_at: Timestamp.fromDate(new Date()),
    };

    await setDoc(doc(documentRef, docId), updates, {
        merge: true,
    }).catch(console.error);

    return updates;
}

In my case, document being updated in updateDocument is always guaranteed to be part of the result set of the query being passed into the onSnapshot.

@vishwa795 vishwa795 added new A new issue that hasn't be categoirzed as question, bug or feature request question labels Jan 9, 2025
@google-oss-bot
Copy link
Contributor

I couldn't figure out how to label this issue, so I've labeled it for a human to triage. Hang tight.

@vishwa795
Copy link
Author

Just incase it helps, this is how I setup auth for firebase

async function initFirebaseAuth(): Promise<User | undefined> {
    try {
        const fetchFirebaseTokenRequest = fetchFirebaseToken();
        const setPersistanceRequest = setPersistence(auth, browserLocalPersistence);

        const [firebaseTokenResponse] = await Promise.all([
            fetchFirebaseTokenRequest,
            setPersistanceRequest,
        ]);

        const firebaseToken = firebaseTokenResponse.data.firebase_token;

        if (!firebaseToken) {
            throw new Error('Firebase token not received for setup');
        }

        const userAuth = await signInWithCustomToken(auth, firebaseToken);

        return userAuth.user;
    } catch (e) {
        console.log('ERROR =====> initFirebaseAuth', e);
    }
}

@jbalidiong jbalidiong added api: firestore needs-attention and removed needs-triage new A new issue that hasn't be categoirzed as question, bug or feature request labels Jan 9, 2025
@ehsannas
Copy link
Contributor

Thanks for reporting @vishwa795.

If you intend to work offline, you should probably not await the setDoc call. LMK if that helps.

Also, I'm curious whether you see the same issue if you use persistentSingleTabManager instead?

@ehsannas ehsannas self-assigned this Jan 10, 2025
@vishwa795
Copy link
Author

vishwa795 commented Jan 11, 2025

If you intend to work offline, you should probably not await the setDoc call. LMK if that helps.

This would just help me resolve the updateDocument function immediately. That will make it seem like the operation has been completed.

But the primary issue I am facing is that, I'm not receiving onSnapshot callbacks when I make setDoc calls offline!

@vishwa795
Copy link
Author

Also, I'm curious whether you see the same issue if you use persistentSingleTabManager instead?

Just tried out with persistentSingleTabManager, I'm seeing the same behaviour after using that as well!

@ehsannas
Copy link
Contributor

Thanks for the update, @vishwa795 . I'll try to reproduce it.

@ehsannas
Copy link
Contributor

ehsannas commented Jan 14, 2025

@vishwa795 I'm not able to reproduce the issue. I see the snapshot listener does indeed get new snapshots when I make updates to a document offline.

@google-oss-bot
Copy link
Contributor

Hey @vishwa795. We need more information to resolve this issue but there hasn't been an update in 5 weekdays. I'm marking the issue as stale and if there are no new updates in the next 5 days I will close it automatically.

If you have more information that will help us get to the bottom of this, just add a comment!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants