Search code examples
firebasegoogle-cloud-firestorebackupspitrpoint-in-time-recovery

How to use Firebase Point-in-time recovery (PITR)?


I have just read the docs on the new Point-in-time recovery (PITR) release which I am absolutely pumped about.

I’m trying to test out the sample code provided by Firebase here for reading a PITR version and can’t get it to work. I have enabled PITR on my Firebase project as instructed in the docs & I’m on the latest version of firebase-admin from NPM.

The code I am using is as follows:

const documentRef = firestore.collection("users").doc("zqN5sVLtCSUkTJqmC64Nsv9mKYD2");

const preUpdate = 1691218778;
const postUpdate = 1691226145;

const timeToUse = preUpdate;

const documentSnapshot = await firestore.runTransaction(
    updateFunction => updateFunction.get(documentRef),
    { readOnly: true, readTime: new Timestamp(timeToUse, 0) }
);

console.log(`Email address at ${moment(timeToUse).format("DD/MM/YYYY HH:mm:ss")} was ${documentSnapshot.data().email}`)

The error that I am getting back from Firestore is as follows:

"error": {
        "code": 3,
        "details": "Invalid transaction.",
        "metadata": {
            "internalRepr": {},
            "options": {}
        },
        "note": "Exception occurred in retry method that was not classified as transient"
    }

Any help / guidance from anyone who has managed to test out PITR would be greatly appreciated!


Solution

  • This was solved thanks to MarkDuckworth on GitHub. The issue seemed to be related to the timestamps being used not being perfectly aligned to minute granularity. The below code worked as expected.

    const ref = firestore.collection("users").doc("zqN5sVLtCSUkTJqmC64Nsv9mKYD2");
    
      const readTimestamp = Timestamp.fromMillis(Date.parse('2023-08-10T12:31:00Z'));
    
      console.log(`PITR READ FOR {${readTimestamp.toMillis()} | ${readTimestamp.toDate().toISOString()}}`);
    
      const querySnapshot = await firestore.runTransaction(
        updateFunction => updateFunction.get(ref),
        { readOnly: true, readTime: readTimestamp }
      );
    
      console.log(querySnapshot.data()?.email);