البدء: كتابة الدوال الأولى واختبارها ونشرها


لبدء استخدام دوال السحابة، يُرجى محاولة العمل من خلال هذا البرنامج التعليمي، الذي يبدأ بمهام الإعداد المطلوبة ويعمل من خلال إنشاء دالتَين مرتبطتَين واختبارهما ونشرهما:

  • إحدى وظائف "إضافة رسالة" التي تعرض عنوان URL يقبل قيمة نصية وتكتبها في Cloud Firestore.
  • دالة "إنشاء أحرف كبيرة" التي تعمل على كتابة النص في Cloud Firestore وتحوّله إلى أحرف كبيرة.

إليك نموذج الرمز الكامل الذي يحتوي على الدوال:

Node.js

// The Cloud Functions for Firebase SDK to create Cloud Functions and triggers.
const {logger} = require("firebase-functions");
const {onRequest} = require("firebase-functions/v2/https");
const {onDocumentCreated} = require("firebase-functions/v2/firestore");

// The Firebase Admin SDK to access Firestore.
const {initializeApp} = require("firebase-admin/app");
const {getFirestore} = require("firebase-admin/firestore");

initializeApp();

// Take the text parameter passed to this HTTP endpoint and insert it into
// Firestore under the path /messages/:documentId/original
exports.addmessage = onRequest(async (req, res) => {
  // Grab the text parameter.
  const original = req.query.text;
  // Push the new message into Firestore using the Firebase Admin SDK.
  const writeResult = await getFirestore()
      .collection("messages")
      .add({original: original});
  // Send back a message that we've successfully written the message
  res.json({result: `Message with ID: ${writeResult.id} added.`});
});

// Listens for new messages added to /messages/:documentId/original
// and saves an uppercased version of the message
// to /messages/:documentId/uppercase
exports.makeuppercase = onDocumentCreated("/messages/{documentId}", (event) => {
  // Grab the current value of what was written to Firestore.
  const original = event.data.data().original;

  // Access the parameter `{documentId}` with `event.params`
  logger.log("Uppercasing", event.params.documentId, original);

  const uppercase = original.toUpperCase();

  // You must return a Promise when performing
  // asynchronous tasks inside a function
  // such as writing to Firestore.
  // Setting an 'uppercase' field in Firestore document returns a Promise.
  return event.data.ref.set({uppercase}, {merge: true});
});

Python

# The Cloud Functions for Firebase SDK to create Cloud Functions and set up triggers.
from firebase_functions import firestore_fn, https_fn

# The Firebase Admin SDK to access Cloud Firestore.
from firebase_admin import initialize_app, firestore
import google.cloud.firestore

app = initialize_app()


@https_fn.on_request()
def addmessage(req: https_fn.Request) -> https_fn.Response:
    """Take the text parameter passed to this HTTP endpoint and insert it into
    a new document in the messages collection."""
    # Grab the text parameter.
    original = req.args.get("text")
    if original is None:
        return https_fn.Response("No text parameter provided", status=400)

    firestore_client: google.cloud.firestore.Client = firestore.client()

    # Push the new message into Cloud Firestore using the Firebase Admin SDK.
    _, doc_ref = firestore_client.collection("messages").add({"original": original})

    # Send back a message that we've successfully written the message
    return https_fn.Response(f"Message with ID {doc_ref.id} added.")


@firestore_fn.on_document_created(document="messages/{pushId}")
def makeuppercase(event: firestore_fn.Event[firestore_fn.DocumentSnapshot | None]) -> None:
    """Listens for new documents to be added to /messages. If the document has
    an "original" field, creates an "uppercase" field containg the contents of
    "original" in upper case."""

    # Get the value of "original" if it exists.
    if event.data is None:
        return
    try:
        original = event.data.get("original")
    except KeyError:
        # No "original" field, so do nothing.
        return

    # Set the "uppercase" field.
    print(f"Uppercasing {event.params['pushId']}: {original}")
    upper = original.upper()
    event.data.reference.update({"uppercase": upper})

لمحة عن هذا الدليل التوجيهي

لقد اخترنا الدالات التي تستخدم Cloud Firestore وHTTP لهذا النموذج، ويرجع ذلك جزئيًا إلى أنّه يمكن اختبار عوامل التشغيل هذه التي تعمل في الخلفية بدقة من خلال مجموعة أدوات المحاكاة المحلية من Firebase. تتوافق مجموعة الأدوات هذه أيضًا مع قاعدة بيانات الوقت الفعلي وCloud Storage وPubSub وAuth وHTTP للمشغلات القابلة للاتصال. يمكن اختبار الأنواع الأخرى من مشغلات الخلفية مثل الإعداد عن بُعد ومشغّلات TestLab بشكل تفاعلي باستخدام مجموعات أدوات غير موضّحة في هذه الصفحة.

توضّح الأقسام التالية من هذا البرنامج التعليمي الخطوات المطلوبة لإنشاء النموذج واختباره ونشره.

إنشاء مشروع في Firebase

  1. في وحدة تحكُّم Firebase، انقر على إضافة مشروع.

    • لإضافة موارد Firebase إلى مشروع حالي على Google Cloud، أدخِل اسم مشروعه أو اختَره من القائمة المنسدلة.

    • لإنشاء مشروع جديد، أدخِل اسم المشروع المطلوب. يمكنك أيضًا تعديل رقم تعريف المشروع المعروض أسفل اسم المشروع اختياريًا.

  2. راجِع بنود Firebase واقبلها إذا طُلب منك ذلك.

  3. انقر على متابعة.

  4. (اختياري) يمكنك إعداد "إحصاءات Google" لمشروعك، ما يتيح لك الحصول على تجربة مثالية باستخدام أيٍّ من منتجات Firebase التالية:

    اختيار حساب حالي على "إحصاءات Google" أو إنشاء حساب جديد

    إذا أنشأت حسابًا جديدًا، اختَر الموقع الجغرافي لإعداد التقارير في "إحصاءات Google"، ثم وافِق على إعدادات مشاركة البيانات وبنود "إحصاءات Google" لمشروعك.

  5. انقر على إنشاء مشروع (أو إضافة Firebase إذا كنت تستخدم مشروعًا حاليًا على Google Cloud).

توفّر منصة Firebase تلقائيًا الموارد لمشروعك في Firebase. عند اكتمال العملية، سيتم توجيهك إلى صفحة النظرة العامة لمشروع Firebase في وحدة تحكُّم Firebase.

إعداد بيئتك وواجهة سطر الأوامر في Firebase

Node.js

ستحتاج إلى بيئة Node.js لكتابة الدوال، وستحتاج إلى واجهة سطر الأوامر في Firebase لنشر الدوال في وقت تشغيل دوال Cloud. لتثبيت Node.js وnpm، يوصى باستخدام مدير إصدارات العقدة.

بعد الانتهاء من تثبيت Node.js وnpm، ثبِّت واجهة سطر الأوامر لمنصة Firebase من خلال طريقتك المفضّلة. لتثبيت واجهة سطر الأوامر عبر npm، استخدِم:

npm install -g firebase-tools

يؤدّي ذلك إلى تثبيت أمر firebase المتوفّر عالميًا. إذا فشل الأمر، قد تحتاج إلى تغيير أذونات npm. للتحديث إلى أحدث إصدار من "firebase-tools"، أعِد تشغيل الأمر نفسه.

Python

ستحتاج إلى بيئة Python لكتابة الدوال، وستحتاج إلى واجهة سطر الأوامر في Firebase لنشر الدوال على وقت تشغيل دوال السحابة. وننصح باستخدام venv لفصل التبعيات. الإصداران 3.10 و3.11 من بايثون.

بعد تثبيت Python، ثبِّت واجهة سطر الأوامر في Firebase باستخدام طريقتك المفضّلة.

تهيئة مشروعك

عند إعداد حزمة تطوير البرامج (SDK) لمنصة Firebase لوظائف Cloud، يتم إنشاء مشروع فارغ يحتوي على التبعيات والحد الأدنى من الرمز البرمجي. إذا كنت تستخدم Node.js، يمكنك اختيار إما TypeScript أو JavaScript لإنشاء الدوال. لأغراض هذا البرنامج التعليمي، ستحتاج أيضًا إلى تهيئة Cloud Firestore.

لتهيئة مشروعك:

  1. شغِّل firebase login لتسجيل الدخول عبر المتصفح ومصادقة واجهة سطر الأوامر في Firebase.
  2. انتقِل إلى دليل مشروعك على Firebase.
  3. قم بتشغيل firebase init firestore. في هذا البرنامج التعليمي، يمكنك قبول القيم الافتراضية عندما يُطلب منك ذلك بشأن قواعد Firestore وملفات الفهرسة. إذا لم تكن قد استخدمت Cloud Firestore في هذا المشروع حتى الآن، ستحتاج أيضًا إلى تحديد وضع البدء والموقع الجغرافي لـ Firestore كما هو موضّح في بدء استخدام Cloud Firestore.
  4. قم بتشغيل firebase init functions. يطالبك واجهة سطر الأوامر باختيار قاعدة تعليمات برمجية حالية أو تهيئة قاعدة جديدة وتسميتها. وعندما تبدأ للتوّ، قد يكون من المناسب إنشاء قاعدة رموز برمجية واحدة في الموقع التلقائي. وفي وقت لاحق، مع توسّع عملية التنفيذ، قد تحتاج إلى تنظيم الدوال في قواعد الرموز.
  5. يوفر لك واجهة سطر الأوامر الخيارات التالية لدعم اللغة:

    • JavaScript
    • TypeScript
    • Python

    بالنسبة إلى هذا البرنامج التعليمي، اختَر JavaScript أو Python. للكتابة باستخدام TypeScript، راجِع كتابة دوالّ باستخدام TypeScript.

  6. يمنحك واجهة سطر الأوامر خيارًا لتثبيت التبعيات. يمكن رفض هذا بأمان إذا كنت تريد إدارة التبعيات بطريقة أخرى.

بعد اكتمال هذه الأوامر بنجاح، يبدو هيكل مشروعك كما يلي:

Node.js

myproject
+- .firebaserc    # Hidden file that helps you quickly switch between
|                 # projects with `firebase use`
|
+- firebase.json  # Describes properties for your project
|
+- functions/     # Directory containing all your functions code
      |
      +- .eslintrc.json  # Optional file containing rules for JavaScript linting.
      |
      +- package.json  # npm package file describing your Cloud Functions code
      |
      +- index.js      # Main source file for your Cloud Functions code
      |
      +- node_modules/ # Directory where your dependencies (declared in
                        # package.json) are installed

بالنسبة إلى Node.js، يحتوي ملف package.json الذي تم إنشاؤه أثناء التهيئة على مفتاح مهم: "engines": {"node": "18"}. يحدد هذا الإصدار إصدار Node.js لكتابة الدوال ونشرها. يمكنك اختيار الإصدارات الأخرى المتوافقة.

Python

myproject
+- .firebaserc    # Hidden file that helps you quickly switch between
|                 # projects with `firebase use`
|
+- firebase.json  # Describes properties for your project
|
+- functions/     # Directory containing all your functions code
      |
      +- main.py      # Main source file for your Cloud Functions code
      |
      +- requirements.txt  #  List of the project's modules and packages 
      |
      +- venv/ # Directory where your dependencies are installed

استيراد الوحدات المطلوبة وإعداد أحد التطبيقات

بعد إتمام مهام الإعداد، يمكنك فتح دليل المصدر وبدء إضافة الرموز كما هو موضح في الأقسام التالية. في هذا النموذج، يجب أن يستورد مشروعك وحدتَي Cloud Functions وAdmin SDK. أضف أسطرًا مثل ما يلي إلى ملفك المصدر:

Node.js

// The Cloud Functions for Firebase SDK to create Cloud Functions and triggers.
const {logger} = require("firebase-functions");
const {onRequest} = require("firebase-functions/v2/https");
const {onDocumentCreated} = require("firebase-functions/v2/firestore");

// The Firebase Admin SDK to access Firestore.
const {initializeApp} = require("firebase-admin/app");
const {getFirestore} = require("firebase-admin/firestore");

initializeApp();

Python

# The Cloud Functions for Firebase SDK to create Cloud Functions and set up triggers.
from firebase_functions import firestore_fn, https_fn

# The Firebase Admin SDK to access Cloud Firestore.
from firebase_admin import initialize_app, firestore
import google.cloud.firestore

app = initialize_app()

تقوم هذه الأسطر بتحميل الوحدات المطلوبة وإعداد مثيل تطبيق admin الذي يمكن إجراء تغييرات من Cloud Firestore منه. أينما كان دعم SDK للمشرف متاحًا، كما هو الحال مع خدمة FCM والمصادقة وقاعدة بيانات Firebase في الوقت الفعلي، فإنّه يوفّر طريقة فعّالة لدمج Firebase باستخدام وظائف السحابة الإلكترونية.

تعمل "واجهة سطر الأوامر في Firebase" على تثبيت وحدتَي SDK لمشرف Firebase وحزمة تطوير البرامج (SDK) لمنصة Firebase لوظائف Cloud تلقائيًا عند إعداد مشروعك. لمزيد من المعلومات حول إضافة مكتبات تابعة لجهات خارجية إلى مشروعك، راجِع التعامل مع التبعيات.

إضافة الوظيفة "إضافة رسالة"

بالنسبة إلى دالة "إضافة رسالة"، أضِف هذه الأسطر إلى الملف المصدر:

Node.js

// Take the text parameter passed to this HTTP endpoint and insert it into
// Firestore under the path /messages/:documentId/original
exports.addmessage = onRequest(async (req, res) => {
  // Grab the text parameter.
  const original = req.query.text;
  // Push the new message into Firestore using the Firebase Admin SDK.
  const writeResult = await getFirestore()
      .collection("messages")
      .add({original: original});
  // Send back a message that we've successfully written the message
  res.json({result: `Message with ID: ${writeResult.id} added.`});
});

Python

@https_fn.on_request()
def addmessage(req: https_fn.Request) -> https_fn.Response:
    """Take the text parameter passed to this HTTP endpoint and insert it into
    a new document in the messages collection."""
    # Grab the text parameter.
    original = req.args.get("text")
    if original is None:
        return https_fn.Response("No text parameter provided", status=400)

    firestore_client: google.cloud.firestore.Client = firestore.client()

    # Push the new message into Cloud Firestore using the Firebase Admin SDK.
    _, doc_ref = firestore_client.collection("messages").add({"original": original})

    # Send back a message that we've successfully written the message
    return https_fn.Response(f"Message with ID {doc_ref.id} added.")

دالة "إضافة رسالة" هي نقطة نهاية HTTP. وينتج عن أي طلب لنقطة النهاية كائنات الطلب والاستجابة التي يتم تمريرها إلى معالج الطلب للنظام الأساسي (onRequest() أو on_request).

دوال HTTP متزامنة (على غرار الدوال القابلة للاستدعاء)، لذا عليك إرسال استجابة في أسرع وقت ممكن وتأجيل العمل باستخدام Cloud Firestore. تمرر دالة HTTP "إضافة رسالة" قيمة نصية إلى نقطة نهاية HTTP وتدرجها في قاعدة البيانات ضمن المسار /messages/:documentId/original.

إضافة الدالة "make uppercase" (استخدام الأحرف الكبيرة)

بالنسبة إلى دالة "make uppercase" (أحرف كبيرة)، أضِف هذه الأسطر إلى الملف المصدر:

Node.js

// Listens for new messages added to /messages/:documentId/original
// and saves an uppercased version of the message
// to /messages/:documentId/uppercase
exports.makeuppercase = onDocumentCreated("/messages/{documentId}", (event) => {
  // Grab the current value of what was written to Firestore.
  const original = event.data.data().original;

  // Access the parameter `{documentId}` with `event.params`
  logger.log("Uppercasing", event.params.documentId, original);

  const uppercase = original.toUpperCase();

  // You must return a Promise when performing
  // asynchronous tasks inside a function
  // such as writing to Firestore.
  // Setting an 'uppercase' field in Firestore document returns a Promise.
  return event.data.ref.set({uppercase}, {merge: true});
});

Python

@firestore_fn.on_document_created(document="messages/{pushId}")
def makeuppercase(event: firestore_fn.Event[firestore_fn.DocumentSnapshot | None]) -> None:
    """Listens for new documents to be added to /messages. If the document has
    an "original" field, creates an "uppercase" field containg the contents of
    "original" in upper case."""

    # Get the value of "original" if it exists.
    if event.data is None:
        return
    try:
        original = event.data.get("original")
    except KeyError:
        # No "original" field, so do nothing.
        return

    # Set the "uppercase" field.
    print(f"Uppercasing {event.params['pushId']}: {original}")
    upper = original.upper()
    event.data.reference.update({"uppercase": upper})

يتم تنفيذ دالة "make uppercase" عند الكتابة إلى Cloud Firestore، مما يؤدي إلى تحديد المستند للاستماع إليه. لأسباب تتعلق بالأداء، ينبغي أن تكون محددًا قدر الإمكان.

الأقواس، مثل {documentId}، تحيط بـ "المَعلمات" وأحرف البدل التي تعرض بياناتها المتطابقة في معاودة الاتصال. تقوم Cloud Firestore باستدعاء معاودة الاتصال عند إضافة رسائل جديدة.

في Node.js، تكون الدوال المستندة إلى الأحداث مثل أحداث Cloud Firestore غير متزامنة. يجب أن تعرض دالة رد الاتصال null أو كائنًا أو Promise. إذا لم تعرض أي شيء، تنتهي مهلة الدالة، وتشير إلى خطأ، ثم تتم إعادة المحاولة. يُرجى الاطّلاع على المزامنة وغير المزامنة والوعد.

محاكاة تنفيذ الدوال

تتيح لك حزمة محاكي Firebase المحلية إنشاء التطبيقات واختبارها على جهازك المحلي بدلاً من نشرها في مشروع على Firebase. يوصى بشدة بإجراء اختبار محلي أثناء التطوير، لأنه يحد من مخاطر أخطاء الترميز التي من المحتمل أن تتكبد تكلفة في بيئة الإنتاج (على سبيل المثال، حلقة لانهائية).

لمحاكاة الدوال:

  1. شغِّل firebase emulators:start وتحقّق من ناتج عنوان URL لواجهة مستخدم Emulator Suite. القيمة التلقائية هي localhost:4000، ولكن يمكن استضافتها على منفذ مختلف على جهازك. أدخِل عنوان URL هذا في المتصفح لفتح واجهة مستخدم Emulator Suite.

  2. تحقَّق من ناتج الأمر firebase emulators:start للاطّلاع على عنوان URL الخاص بدالة HTTP. سيبدو مشابهًا لـ http://localhost:5001/MY_PROJECT/us-central1/addMessage، باستثناء ما يلي:

    1. سيتم استبدال MY_PROJECT برقم تعريف مشروعك.
    2. قد يكون المنفذ مختلفًا على جهازك المحلي.
  3. أضِف سلسلة طلب البحث ?text=uppercaseme إلى نهاية عنوان URL للدالة. من المفترض أن يبدو هذا على النحو التالي: http://localhost:5001/MY_PROJECT/us-central1/addMessage?text=uppercaseme. يمكنك بشكل اختياري تغيير الرسالة ذات الحالة "كبيرة الحجم" إلى رسالة مخصّصة.

  4. يمكنك إنشاء رسالة جديدة من خلال فتح عنوان URL في علامة تبويب جديدة في المتصفّح.

  5. عرض تأثيرات الدوال في واجهة مستخدم Emulator Suite:

    1. في علامة التبويب السجلات، من المفترض أن تظهر لك سجلات جديدة تشير إلى تشغيل وظائف HTTP بنجاح:

      i functions: Beginning execution of "addMessage"

      i functions: Beginning execution of "makeUppercase"

    2. في علامة التبويب Firestore، من المفترض أن ترى مستندًا يحتوي على رسالتك الأصلية بالإضافة إلى النسخة ذات الأحرف الكبيرة من رسالتك (إذا كانت في الأصل "أحرف كبيرة"، ستظهر لك حالة الأحرف الكبيرة).

نشر الدوال في بيئة إنتاج

وبمجرد أن تعمل الدوال على النحو المطلوب في المحاكي، يمكنك متابعة نشرها واختبارها وتشغيلها في بيئة الإنتاج. ضع في اعتبارك أنه للنشر في الإنتاج، يجب أن يكون مشروعك على خطة أسعار Blaze. يُرجى الاطّلاع على أسعار Cloud Functions.

لإكمال البرنامج التعليمي، انشر الدوال ثم تنفذها.

  1. نفِّذ هذا الأمر لنشر الدوال:

     firebase deploy --only functions
     

    بعد تنفيذ هذا الأمر، تعرض واجهة سطر الأوامر في Firebase عنوان URL لأي نقاط نهاية لدالة HTTP. في الوحدة الطرفية، من المفترض أن يظهر سطر على النحو التالي:

    Function URL (addMessage): https://us-central1-MY_PROJECT.cloudfunctions.net/addMessage
    

    يحتوي عنوان URL على رقم تعريف مشروعك ومنطقة لدالة HTTP. لا داعي للقلق بشأن ذلك في الوقت الحالي، إلا أنّ بعض دوال HTTP للإنتاج يجب أن تحدّد موقعًا جغرافيًا لتقليل وقت استجابة الشبكة.

    إذا واجهت أخطاء في الوصول، مثل "يتعذّر منح الإذن بالوصول إلى المشروع"، جرِّب التحقّق من الاسم المستعار للمشروع.

  2. باستخدام إخراج عنوان URL من خلال واجهة سطر الأوامر، أضف معلمة طلب بحث نصيًا وافتحها في أحد المتصفحات:

    https://us-central1-MY_PROJECT.cloudfunctions.net/addMessage?text=uppercasemetoo
    

    تنفِّذ الدالة وتعيد توجيه المتصفح إلى وحدة تحكُّم Firebase في موقع قاعدة البيانات الذي يتم فيه تخزين السلسلة النصية. يؤدّي حدث الكتابة هذا إلى تشغيل الدالة "make uppercase" التي تكتب نسخة كبيرة من السلسلة.

بعد نشر الوظائف وتنفيذها، يمكنك عرض السجلات في Google Cloud Console. إذا كنت بحاجة إلى حذف وظائف قيد التطوير أو الإنتاج، استخدِم واجهة سطر الأوامر في Firebase.

في مرحلة الإنتاج، قد تحتاج إلى تحسين أداء الوظيفة والتحكّم في التكاليف من خلال ضبط حد أدنى وحد أقصى لعدد الأجهزة التي يتم تشغيلها. راجِع التحكّم في سلوك التوسيع للحصول على مزيد من المعلومات حول خيارات وقت التشغيل هذه.

الخطوات اللاحقة

في هذه المستندات، يمكنك معرفة المزيد من المعلومات حول كيفية إدارة الدوال لدوال السحابة بالإضافة إلى كيفية التعامل مع جميع أنواع الأحداث التي تتيحها دوال Cloud.

لمعرفة المزيد حول دوال السحابة، يمكنك أيضًا القيام بما يلي: