jamelkenya.com

Mastering Firebase Cloud Functions to Avoid Infinite Loops

Written on

Understanding Firebase Firestore Limitations

In my applications, I utilize Firebase Firestore, which generally performs well. However, it does have some limitations, particularly with full-text search capabilities. Today, I want to address another challenge I encountered: managing timestamps.

While timestamps may seem straightforward—simply save DateTime.now() to the database—the accuracy of this approach hinges on the user's device time being correct. Although most users maintain accurate device times, some may deliberately set their clocks forward to exploit certain games. I want to ensure my application remains robust in these scenarios. So, what are the alternatives?

Fortunately, Firebase offers FieldValue.serverTimestamp(), which allows you to update a document with a server-generated timestamp. This feature works well for obtaining the current server time, but if you need a timestamp set for a future time (e.g., five hours ahead), it falls short. Although the Firebase team might address this in the future—there's already FieldValue.increment(int num) for numerical fields—there's currently no straightforward method for manipulating timestamps. This is where Firebase Cloud Functions come into play.

Firebase Cloud Functions provide the ability to execute functions on Google's servers, enabling powerful integrations with other Firebase services. Additionally, you can listen for various database events, specifically:

  • onDocumentCreated
  • onDocumentUpdated
  • onDocumentDeleted
  • onDocumentWritten

However, proceed with caution:

Infinite Loop Risks in Document Listeners

When working with document listeners, updating a document can trigger the listener again, leading to potential infinite loops if not handled correctly. I experienced this firsthand but fortunately had a failsafe in place. Previously, I discussed this failsafe in a post about securing API keys, where I shared a function that rate limits API calls.

This same approach is effective for preventing infinite loops caused by document updates. For example, by using the following code:

if (await isRateLimited("Read", 10)) {

return;

}

This line of code prevented my function from entering an endless cycle of recursive calls. You might think that you’d never make such a mistake, but I was surprised to discover two bugs that led to such issues.

The first bug stemmed from how I checked whether to cancel the request. My logic involved checking if the timestamp had changed; if not, the code would do nothing. However, the timestamp shifted by a few nanoseconds with each invocation, causing the loop to persist. Whoops!

The second issue was the infamous Firestore proprietary timestamp format. Instead of providing a native JavaScript Date object, Firestore returns its own timestamp object. I had encountered this problem before in Flutter and learned that you must convert each Firestore timestamp to a native object manually. Here’s how I handle it:

const nativeDate = new Date(firestoreTimestamp.seconds * 1000);

Key Takeaway

The main lesson here is the importance of exercising caution with recursive functions that can incur costs for every invocation. Consequently, I’ve decided to keep the rate-limiting code in production—albeit set to a higher threshold, around 100 invocations (I’m aiming for more users). I also modified it to log the current time when the rate limit is reached, allowing me to investigate and adjust as needed.

Here’s the final code snippet I implemented:

// Final code example...

Initially, when I wrote this cloud function, I didn’t anticipate encountering any issues. I had tested getNewDateTimeForAccountDeletion() and was confident it would work. However, I realized I hadn’t conducted sufficient testing. Thankfully, my failsafe was in place; otherwise, my Firebase bill could have skyrocketed, and I might have found myself pleading with Google to waive those charges.

This experience has been a mixed blessing. I've learned how easily infinite loops can arise in code, yet I also feel more confident in my ability to work with Cloud Functions. While I could have relied on the user's device for accurate timestamps, I wanted to deepen my understanding of Cloud Functions—and I certainly achieved that goal.

Future Aspirations

I’ve been contemplating the migration of my entire backend from a somewhat clunky VPS setup to a fully Firebase-based backend. This exercise has significantly advanced that ambition.

If you found this post insightful and wish to keep up with my future articles, consider using my RSS app, Stratum, available on iOS and Android. Also, check out my language learning app, Litany (iOS, Android).

Chapter 2: Implementing Location-Based Apps with Google Maps

Explore how to create location-based applications using Google Maps with FlutterFlow. This video provides a comprehensive overview of the development process.

Chapter 3: Crafting Subtle Yet Engaging Scroll Animations

Discover techniques for implementing elegant scroll animations that enhance user experience in your applications. This video showcases practical examples and tips.

Share the page:

Twitter Facebook Reddit LinkIn

-----------------------

Recent Post:

Robotic Innovations: How Technology Can Support Our Bees

Explore how robotic technology is being utilized to aid bee populations and enhance beekeeping practices.

The Living Essence: Unveiling Consciousness in the Universe

This article explores the concept of consciousness in everything, suggesting that all entities, living or non-living, possess awareness.

Avoiding Job Loss: Top 10 Developer Behaviors to Avoid

Developers can easily jeopardize their careers through certain behaviors. Here are ten habits to avoid to ensure job security.

Understanding the Mysterious Decline of Our Memory

Exploring the effects of stress and sleep deprivation on memory.

Understanding the Intricacies of Spacetime and Its Cosmic Significance

An exploration of spacetime, its relationship with space, and its implications in astronomy.

Boost Your Productivity with These 5 Essential Chrome Extensions

Discover five lesser-known Chrome extensions that can significantly enhance your online productivity.

Landing on Mars: The Challenges and Triumphs of Space Exploration

Discover the complexities and historical efforts behind successfully landing on Mars, from early missions to modern advancements.

Exploring the Future: Insights from

Dive into Yuval Noah Harari's