我可以联系我开发的firebase功能中的重大性能退化的帮助。此功能通过条纹处理付款接收,生成QR码,并在保留期间在多个Firestore收集中记录数据。

问题描述 投票:0回答:1
-减小生成的QR码的大小。

-减少传输到firestore的数据量。

尽管采取了这些行动,但问题仍然存在并显着影响我们的门票创建过程。 我将非常感谢您的经验中的任何建议或见解,以帮助确定这些延迟的原因并实施必要的解决方案。

提前感谢您的协助和专业知识。

const { setGlobalOptions } = require('firebase-functions/v2'); setGlobalOptions({ region: "europe-west3", }); const functions = require('firebase-functions'); const admin = require('firebase-admin'); const stripe = require('stripe')('---'); const axios = require('axios'); const QRCode = require('qrcode'); const { Storage } = require('@google-cloud/storage'); const storage = new Storage(); const { firestore } = require('firebase-admin'); const cors = require('cors')({ origin: true }); admin.initializeApp(); exports.stripeWebhook = functions.https.onRequest((req, res) => { cors(req, res, async () => { let event; try { event = stripe.webhooks.constructEvent( req.rawBody, req.headers['stripe-signature'], '---' ); } catch (err) { } if (event.type === 'checkout.session.completed') { const session = event.data.object; const data = extractDataFromSession(session); // Parsing du champ tickets (JSON) let ticketsArray = []; try { ticketsArray = JSON.parse(data.tickets); console.log("Tickets extraits:", ticketsArray); } catch (err) { console.error("Erreur lors du parsing des tickets:", err.message); return res.status(400).send("Tickets invalides dans les metadata."); } if (!Array.isArray(ticketsArray) || ticketsArray.length === 0) { console.error("Aucun ticket trouvé."); return res.status(400).send("Aucun ticket trouvé."); } // Réponse immédiate à Stripe (code 200) res.status(200).send({ received: true }); // Traitement complet en arrière-plan (ne bloque pas la réponse) (async () => { try { for (const ticket of ticketsArray) { for (let i = 0; i < ticket.quantity; i++) { const ticketData = { locaImageUrl: data.localisationImageUrl, garantis_: data.garantis_, email: data.email, sexe: data.sexe, total: data.totalA, uid: data.uid, name: data.name, namePro: data.namePro, etc... etc }; const qr = await uniqueCodeCreate(ticketData); const publicUrl = await createAndUploadQRCode(ticketData, qr, 256, 'M'); await reservationAndProDetailsToFirestore(ticketData, publicUrl, qr); await sendQrCodeEmail(ticketData, publicUrl, qr); } } } catch (error) { console.error("Erreur lors du traitement asynchrone:", error); } })(); } else { res.status(400).send("Type d’événement non géré"); } }); }); function extractDataFromSession(session) { return { localisationImageUrl: session.metadata.localisationImageUrl, garantis_: session.metadata.garantis_, email: session.metadata.email, sexe: session.metadata.sexe, total: session.metadata.total, uid: session.metadata.uid, etc..etc..etc }; } async function uniqueCodeCreate(data) { const prenom = data.name; const rng = Math.floor(Math.random() * ____); const qr = ____; return qr; } async function sendQrCodeEmail(data, publicUrl, qr) { try { const fraix = isNaN(parseFloat(data.ticketPriceFraix)) ? 0.0 : parseFloat(data.ticketPriceFraix); const amount = parseFloat(data.ticketPrice); const dateDebutTimestamp = admin.firestore.Timestamp.fromDate(new Date(data.dateDebut)); const url = '---'; // Envoi de la requête POST à l'API const response = await axios.post(url, { localisationImageUrl: "", resaID: qr, dateDebut: dateDebutTimestamp, etc...etc... }); // Vérification de la réponse if (response.status !== 200) { } return { success: true, message: "Email sent successfully." }; } catch (error) { let errorMessage = "Error sending QR code email"; if (error.response) { console.error("Erreur dans la réponse:", error.response.status); console.error("Détails de l'erreur:", error.response.data); errorMessage += : Server responded with status: ${error.response.status}; } else if (error.request) { console.error("Erreur dans la requête:", error.request); errorMessage += ": No response received"; } else { console.error('Erreur lors de la configuration de la requête:', error.message); errorMessage += : Request setup failed: ${error.message}; } return { success: false, message: errorMessage }; } } async function createAndUploadQRCode(data, qr, width = 256, errorCorrectionLevel = 'M') { try { const options = { color: { dark: "#000000", light: "#0000" }, width: width, errorCorrectionLevel: errorCorrectionLevel, }; const qrCodeBuffer = await QRCode.toBuffer(qr, options); const bucket = admin.storage().bucket(); const filePath = EventsFile/${---}/${data.---}/---/${---}.png; const file = bucket.file(filePath); await file.save(qrCodeBuffer, { contentType: 'image/png', public: true }); console.log("QR code uploadé."); const publicUrl = https://storage.googleapis.com/${bucket.name}/${file.name}; return publicUrl; } catch (error) { throw error; } } async function reservationAndProDetailsToFirestore(data, publicUrl, qr) { try { // Initialisation locale de Firestore const firebaseFirestore = firestore(); const fraix = isNaN(parseFloat(data.ticketPriceFraix)) ? 0.0 : parseFloat(data.ticketPriceFraix); const amount = parseFloat(data.ticketPrice); const dateDebutTimestamp = admin.firestore.Timestamp.fromDate(new Date(data.dateDebut)); const dateFinTimestamp = admin.firestore.Timestamp.fromDate(new Date(data.dateFin)); const now = new Date(); const resaModel = { ...//...//... }; const resaDetails = { ...//...//... }; const historiqueDetails = { ...//...//... }; const clientInfo = { ...//...//... }; const historiqueClientDetails = { ...//...//... }; const postRef = firebaseFirestore .collection("--") .doc(--) .collection("--") .doc(--); const postUpdateData = { '--': admin.firestore.FieldValue.increment(amount), [--]: firestore.FieldValue.increment(-1), [--]: firestore.FieldValue.increment(1) }; if (data.sexe === '--') { postUpdateData['--'] = firestore.FieldValue.increment(1); } else if (data.-- === '--') { postUpdateData['--'] = firestore.FieldValue.increment(1); } const batch = firebaseFirestore.batch(); // Ajout des écritures dans le batch : batch.set( firebaseFirestore.collection("--").doc(--).collection("-- --").doc(--), ); batch.set( firebaseFirestore.collection("--").doc(--).collection("Reservation").doc(--), resaDetails ); batch.set( firebaseFirestore.collection("--").doc(--).collection("-- --").doc(--), historiqueDetails ); const clientDocRef = firebaseFirestore.collection("--").doc(--).collection("--").doc(--); batch.set(clientDocRef, clientInfo, { merge: true }); batch.set(clientDocRef.collection("--").doc(--), historiqueClientDetails); batch.update(postRef, { ...postUpdateData, Like: admin.firestore.FieldValue.increment(1) }); // Modification : retourner la promesse du commit return batch.commit().then(() => { console.timeEnd("batchCommit"); console.log("=== Fin de combinedReservationAndHistoryToFirestore ==="); return { success: true, message: "" }; }); } catch (error) { console.error("", error); return { success: false, message: "" }; } }

HTTP Cloud功能在一旦将响应发送给呼叫者,它被认为是“完成的”。寄回响应后尝试的任何工作都可能永远不会执行,如果这样做,则在此处记录了

,并且某些网络请求可能会被阻止,从而导致其他问题。

在您的情况下,您告诉云功能运行时,在调用以下任何一条行时,您的功能已完成:

res.status(200).send({ received: true });

or

res.status(400).send("Type d’événement non géré");

您应该将这些行对待这些行,就像它们在开始时具有

return

,在此之后可以运行更多代码。

如果以快速,及时的方式向您的功能的呼叫者发送响应很重要(Stripe
推荐),接受请求,验证并将相关数据保存到实时数据库或云Firestore,然后将响应发送回呼叫者。在单独的云功能中,将其配置为收听该数据库添加,然后对其进行采取行动,以执行您需要执行的任何背景任务。
firebase google-cloud-functions
1个回答
0
投票

将您的代码捕获以实现这一目标超出了StackoverFlow的范围。但这是您需要执行的步骤:

HTTP请求处理程序

Accept HTTP请求

估算请求

将请求数据保存到实时数据库或CloudFirestore

对呼叫者的确认书进行回信,理想情况下,提供有关在何处获得状态更新的信息。 (有关此的一般形式,请参见
HTTP202接受

流)


background任务

trigger基于上面步骤3中的数据库调用trigger

RTDB云函数或CloudFirestore Cloud函数

阅读请求数据

执行背景任务


用结果添加数据库(以便用户/管理员可以检查是否完成)

如果您期望高音量,并且不需要任务进度跟踪,则可以调用Pub/sub事件云功能

而不是覆盖的其他线程
    。但是,对于诸如Stripe帐单之类的东西,当您需要追逐诸如重复付款之类的事情时,我会选择更好的可审核性。
最新问题
© www.soinside.com 2019 - 2025. All rights reserved.