From fc3b4cce98d55d7271bc884e3992b322edeefec8 Mon Sep 17 00:00:00 2001 From: Vaibhav Surana Date: Mon, 20 Nov 2023 15:22:49 +0530 Subject: [PATCH] feat: log firebase errors to console (#79) * feat: log firebase errors to console * updated package version to 0.8.3-beta --- package.json | 2 +- src/firebase-adapter.ts | 141 +++++++++++++++++++++++----------------- 2 files changed, 82 insertions(+), 61 deletions(-) diff --git a/package.json b/package.json index 083f066b0..be4a7407e 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@hackerrank/firepad", "description": "Collaborative text editing powered by Firebase", - "version": "0.8.2-beta", + "version": "0.8.3-beta", "author": { "email": "bprogyan@gmail.com", "name": "Progyan Bhattacharya", diff --git a/src/firebase-adapter.ts b/src/firebase-adapter.ts index 2b692bffd..5c32c1370 100644 --- a/src/firebase-adapter.ts +++ b/src/firebase-adapter.ts @@ -255,25 +255,29 @@ export class FirebaseAdapter implements IDatabaseAdapter { */ protected _monitorHistory(): void { // Get the latest checkpoint as a starting point so we don't have to re-play entire history. - this._databaseRef!.child("checkpoint").once("value", (snapshot) => { - if (this._zombie) { - // just in case we were cleaned up before we got the checkpoint data. - return; - } + this._databaseRef!.child("checkpoint") + .once("value", (snapshot) => { + if (this._zombie) { + // just in case we were cleaned up before we got the checkpoint data. + return; + } - const revisionId: string | null = snapshot.child("id").val(); - const op: TextOperationType | null = snapshot.child("o").val(); - const author: UserIDType | null = snapshot.child("a").val(); + const revisionId: string | null = snapshot.child("id").val(); + const op: TextOperationType | null = snapshot.child("o").val(); + const author: UserIDType | null = snapshot.child("a").val(); - if (op != null && revisionId != null && author !== null) { - this._pendingReceivedRevisions[revisionId] = { o: op, a: author }; - this._checkpointRevision = this._revisionFromId(revisionId); - this._monitorHistoryStartingAt(this._checkpointRevision + 1); - } else { - this._checkpointRevision = 0; - this._monitorHistoryStartingAt(this._checkpointRevision); - } - }); + if (op != null && revisionId != null && author !== null) { + this._pendingReceivedRevisions[revisionId] = { o: op, a: author }; + this._checkpointRevision = this._revisionFromId(revisionId); + this._monitorHistoryStartingAt(this._checkpointRevision + 1); + } else { + this._checkpointRevision = 0; + this._monitorHistoryStartingAt(this._checkpointRevision); + } + }) + .catch((err) => { + console.error("[firebase] Error getting checkpoint", err); + }); } /** @@ -305,9 +309,13 @@ export class FirebaseAdapter implements IDatabaseAdapter { this._firebaseOn(historyRef, "child_added", this._historyChildAdded, this); - historyRef.once("value", () => { - this._handleInitialRevisions(); - }); + historyRef + .once("value", () => { + this._handleInitialRevisions(); + }) + .catch((err) => { + console.error("[firebase] Error getting initial revisions", err); + }); } /** @@ -479,43 +487,52 @@ export class FirebaseAdapter implements IDatabaseAdapter { revisionData: FirebaseOperationDataType, callback: SendOperationCallbackType ): void { - this._databaseRef!.child("history") - .child(revisionId) - .transaction( - (current) => { - if (current === null) { - return revisionData; - } - }, - (error, committed) => { - if (error) { - if (error.message === "disconnect") { - if (this._sent && this._sent.id === revisionId) { - // We haven't seen our transaction succeed or fail. Send it again. - setTimeout(() => { - this._doTransaction(revisionId, revisionData, callback); - }); - } - - return callback(error, false); - } else { - this._trigger( - FirebaseAdapterEvent.Error, - error, - revisionData.o.toString(), - { - operation: revisionData.o.toString(), - document: this._document!.toString(), + try { + this._databaseRef!.child("history") + .child(revisionId) + .transaction( + (current) => { + if (current === null) { + return revisionData; + } + }, + (error, committed) => { + console.error("[firebase] Transaction error - onComplete", error); + + if (error) { + if (error.message === "disconnect") { + if (this._sent && this._sent.id === revisionId) { + // We haven't seen our transaction succeed or fail. Send it again. + setTimeout(() => { + this._doTransaction(revisionId, revisionData, callback); + }); } - ); - Utils.onFailedDatabaseTransaction(error.message); + + return callback(error, false); + } else { + this._trigger( + FirebaseAdapterEvent.Error, + error, + revisionData.o.toString(), + { + operation: revisionData.o.toString(), + document: this._document!.toString(), + } + ); + Utils.onFailedDatabaseTransaction(error.message); + } } - } - return callback(null, committed); - }, - false - ); + return callback(null, committed); + }, + false + ) + .catch((error) => { + console.error("[firebase] Transaction error - catch()", error); + }); + } catch (error) { + console.error("[firebase] Transaction error - trycatch", error); + } } /** @@ -550,12 +567,16 @@ export class FirebaseAdapter implements IDatabaseAdapter { * Updates current document state into `checkpoint` node in Firebase. */ protected _saveCheckpoint(): void { - this._databaseRef!.child("checkpoint").set({ - a: this._userId, - o: this._document!.toJSON(), - // use the id for the revision we just wrote. - id: this._revisionToId(this._revision - 1), - }); + this._databaseRef!.child("checkpoint") + .set({ + a: this._userId, + o: this._document!.toJSON(), + // use the id for the revision we just wrote. + id: this._revisionToId(this._revision - 1), + }) + .catch((err) => { + console.error("[firebase] Error saving checkpoint", err); + }); } isHistoryEmpty(): boolean {