在 firebase onSnapshot 和 Cloud Functions 之间做出选择吗?

问题描述 投票:0回答:1
useEffect(()=>{
    if(!user){
      return;
    }
    const creationTime = user.metadata?.creationTime;

    if (!creationTime) {
      setLoading(false);
      return;
    }

    const userCreationDate = new Date(creationTime);
    const currentDate = new Date();
    const diffTime = Math.abs(currentDate.getTime() - userCreationDate.getTime());
    const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));

    const db = getFirestore(app);
    const userRef = doc(db, 'users', user.uid);

    if (diffDays < 7) {
      setIsSubscribed(true);
      setLoading(false);
      return;
    }

    const unsubscribeSnapshot = onSnapshot(userRef, (userDoc) => {
      console.log('In unsubscribeSnapshot');
      if (userDoc.exists()) {
        const userData = userDoc.data();
        const subscribed = userData.isSubscribed;

        if (!subscribed) {
          router.push('/signUp');
          setLoading(false);
          return;
        }
        setIsSubscribed(subscribed);
      } else {
        setIsSubscribed(false);
        router.push('/signUp');
      }
      setLoading(false);
    });

    setUnsubscribeSnapshot(() => unsubscribeSnapshot);

    return () => {
      if (unsubscribeSnapshot) {
        unsubscribeSnapshot();
      }
    };
  },[router, user]);


import { FirebaseApp } from 'firebase/app';
import { getFirestore, doc, setDoc } from 'firebase/firestore';
import { getAuth } from 'firebase/auth';

const updateSubscriptionStatus = async (
  app: FirebaseApp,
  isSubscribed: boolean,
  customerId: string,
) => {
  const auth = getAuth(app);
  const userId = auth.currentUser?.uid;
  if (!userId) {
    console.error('User is not authenticated');
    throw new Error('User is not authenticated');
  }

  const db = getFirestore(app);
  const userRef = doc(db, 'users', userId);
  await setDoc(userRef, { isSubscribed, stripeCustomerId: customerId }, { merge: true });
};

export default updateSubscriptionStatus;


  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    if (!stripe || !elements) {
      return;
    }
    setIsLoading(true);

    const result = (await stripe.confirmPayment({
      elements,
      redirect: 'if_required',
    })) as PaymentIntentResult;

    if (result.error) {
      setMessage(result.error.message || 'An unexpected error occurred.');
    } else if (result.paymentIntent && result.paymentIntent.status === 'succeeded') {
      try {
        await updateSubscriptionStatus(app, true, customerId);
        setMessage('Payment successful!');
        router.push('/thanks');
      } catch (error) {
        setMessage('Failed to update subscription status.');
        console.error(error);
      }
    } else {
      setMessage('Payment processing.');
    }
    setIsLoading(false);
  };

我目前正在管理一个订阅系统,每个用户都可以获得 7 天的免费试用期。在此试验期间,本地

isSubscribed
变量设置为 true,允许用户访问所有页面。试用期结束后,
isSubscribed
设置为 false,并在 Firestore 中创建相应变量并将其更新为 false。这会限制对所有页面的访问,并且用户将被重定向到注册页面。

用户完成注册过程并设置每月订阅后,Firestore

isSubscribed
变量和本地 isSubscribed 变量都会更新为 true,从而恢复对页面的访问。

我还设置了一个 Stripe API Webhook,根据每月付款的成功或失败自动更新 Firestore isSubscribed 状态,从而更新本地 isSubscribed 变量。

我的问题是我是否应该使用 Cloud Functions 而不是

onSnapshot
,因为我将拥有大约 1,000 个用户,每个用户都接受 7 天的免费试用,并且他们的
isSubscribed
状态将由他们的每月付款决定。

我目前正在使用

onSnapshot
,它运行良好,但我担心它的性能和成本影响。

javascript firebase google-cloud-platform google-cloud-firestore google-cloud-functions
1个回答
0
投票

我的问题是我是否应该使用 Cloud Functions 而不是

onSnapshot
,因为我将拥有大约 1,000 个用户,每个用户都接受 7 天的免费试用,并且他们的
isSubscribed
状态将由他们的每月付款决定。

我目前正在使用

onSnapshot
,它运行良好,但我担心它的性能和成本影响。

在考虑性能和成本影响之前,您应该了解这两种方法之间的区别。首先,您应该知道

onSnapshot
(实时监听器)的工作方式与Cloud Functions的工作方式不兼容。 Cloud Functions for Firebase 只能运行一段“有限”的时间,据我所知,最长为 9 分钟,之后它将被关闭。所以你不能用它们来代替监听器。所以云函数肯定不太适合需要长时间监听实时更新的情况。另一方面,实时侦听器将继续侦听,直到它们被“明确”删除。因此,如果您尝试在 Cloud Function 内部附加侦听器,Firebase 服务器仍会在 9 分钟后将其关闭。 因此,我建议您在客户端上附加一个实时侦听器,以便您始终可以从 Firebase 服务器获取实时更新,并仅使用 Cloud Function 来响应 Firestore 中文档内发生的事件。

© www.soinside.com 2019 - 2024. All rights reserved.