Sitelet https://github.com/firebase/flutterfire/issues/10153
Skip to content

馃悰 [cloud_firestore] old data retrieved if get is called just after a transaction when a stream is active聽#10153

Description

@pldelattre

Bug report

Describe the bug
Firestore doesn't retrieve the latest data when using 'get' on a document just after this document was modified through a transaction and a stream to listen on the same document is active

Steps to reproduce

Steps to reproduce the behavior:

  1. Listen to a document
  2. Update this document via a transaction
  3. Call get method on this document just after transaction has succeeded.

Expected behavior

Content of the retrieved document in the 'Get' call should be updated but it is not !
This issue is not happening if we are not listening to the document OR if the document is not updated through a transaction.

Sample project

To reproduce the problem.

  • Create a 'test' collection with a 'test' document. Add a 'population' field to this document with a number value of 1.
  • Run the following widget.
  • Issue will appear if you click 'Listen to the stream' and then 'Transact then Get'
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';

class TestBugWidget extends StatefulWidget {
  const TestBugWidget({super.key});

  @override
  State<TestBugWidget> createState() => _TestBugWidgetState();
}

class _TestBugWidgetState extends State<TestBugWidget> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Bug repro')),
      body: Column(children: [
        ListTile(
          title: const Text('Listen to the stream'),
          onTap: streamListen,
        ),
        ListTile(
          title: const Text('Update then Get'),
          onTap: updateThenGet,
        ),
        ListTile(
          title: const Text('Transact then Get'),
          onTap: transactThenGet,
        )
      ]),
    );
  }

  void streamListen() {
    FirebaseFirestore.instance
        .collection('test')
        .doc('test')
        .snapshots()
        .listen((event) {
      debugPrint('new test has arrived');
    });
  }

  Future<void> transactThenGet() async {
    final docRef = FirebaseFirestore.instance.collection("test").doc("test");
    var newPopulation;
    await FirebaseFirestore.instance.runTransaction((transaction) async {
      final snapshot = await transaction.get(docRef);
      final prevPopulation = snapshot.get("population");
      newPopulation = prevPopulation + 1;
      transaction.update(docRef, {"population": newPopulation});
    });
    Map<String, dynamic> updated = (await docRef.get()).data()!;
    debugPrint('Expecting : ${newPopulation.toString()}');
    debugPrint('Got : ${updated['population'].toString()}');
  }

  Future<void> updateThenGet() async {
    final docRef = FirebaseFirestore.instance.collection("test").doc("test");
    final snapshot = await docRef.get();
    final prevPopulation = snapshot.get("population");
    final newPopulation = prevPopulation + 1;
    await docRef.update({"population": newPopulation});
    Map<String, dynamic> updated = (await docRef.get()).data()!;
    debugPrint('Expecting : ${newPopulation.toString()}');
    debugPrint('Got : ${updated['population'].toString()}');
  }
}

Additional context

cloud_firestore: ^4.0.5
firebase_core: ^2.2.0

I tested both on Android and Web. Issue happens in both cases.

Activity

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

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions