1. نظرة عامة
في المختبرات السابقة، أنشأت إصدارًا مستندًا إلى الأحداث من تطبيق Pic-a-daily استخدم وظيفة Cloud Function تم تشغيلها من خلال Google Cloud Storage لخدمة "تحليل الصور"، وحاوية Cloud Run تم تشغيلها من خلال GCS عبر Pub/Sub لخدمة "الصور المصغّرة"، وEventarc لتشغيل خدمة "جامع البيانات غير المرغوب فيها للصور" على Cloud Run. كانت هناك أيضًا خدمة Collage يتم تشغيلها من خلال Cloud Scheduler:

في هذا التمرين العملي، ستنشئ نسخة منظَّمة من التطبيق. وبدلاً من تدفّق أنواع مختلفة من الأحداث عبر النظام، ستستخدم "سير العمل" لتنظيم الخدمات واستدعائها على النحو التالي:

ما ستتعلمه
- App Engine
- Cloud Firestore
- وظائف السحابة الإلكترونية
- Cloud Run
- Workflows
2. الإعداد والمتطلبات
إعداد البيئة بالسرعة التي تناسبك
- سجِّل الدخول إلى Cloud Console وأنشِئ مشروعًا جديدًا أو أعِد استخدام مشروع حالي. (إذا لم يكن لديك حساب على Gmail أو Google Workspace، عليك إنشاء حساب).



تذكَّر رقم تعريف المشروع، وهو اسم فريد في جميع مشاريع Google Cloud (الاسم أعلاه مستخدَم حاليًا ولن يكون متاحًا لك، نأسف لذلك). سيتم الإشارة إليه لاحقًا في هذا الدرس التطبيقي حول الترميز باسم PROJECT_ID.
- بعد ذلك، عليك تفعيل الفوترة في Cloud Console من أجل استخدام موارد Google Cloud.
لن تكلفك تجربة هذا الدرس البرمجي الكثير من المال، إن وُجدت تكلفة على الإطلاق. احرص على اتّباع أي تعليمات في قسم "التنظيف" الذي ينصحك بكيفية إيقاف الموارد حتى لا يتم تحصيل رسوم منك بعد هذا البرنامج التعليمي. يمكن لمستخدمي Google Cloud الجدد الاستفادة من برنامج الفترة التجريبية المجانية بقيمة 300 دولار أمريكي.
بدء Cloud Shell
على الرغم من إمكانية تشغيل Google Cloud عن بُعد من الكمبيوتر المحمول، ستستخدم في هذا الدرس التطبيقي حول الترميز Google Cloud Shell، وهي بيئة سطر أوامر تعمل في السحابة الإلكترونية.
من وحدة تحكّم Google Cloud Platform، انقر على رمز Cloud Shell في شريط الأدوات العلوي الأيسر:

لن يستغرق توفير البيئة والاتصال بها سوى بضع لحظات. عند الانتهاء، من المفترض أن يظهر لك ما يلي:

يتم تحميل هذه الآلة الافتراضية مزوّدة بكل أدوات التطوير التي ستحتاج إليها. توفّر هذه الخدمة دليلًا منزليًا دائمًا بسعة 5 غيغابايت، وتعمل على Google Cloud، ما يؤدي إلى تحسين أداء الشبكة والمصادقة بشكل كبير. يمكن إكمال جميع المهام في هذا التمرين المعملي باستخدام متصفّح فقط.
3- مقدمة عن Workflows

يمكنك استخدام خطوات سير العمل لإنشاء خطوات سير عمل بدون خادم تربط سلسلة من المهام بدون خادم معًا بالترتيب الذي تحدّده. يمكنك الجمع بين قوة واجهات برمجة التطبيقات من Google Cloud ومنتجات الحوسبة بدون خادم، مثل Cloud Functions وCloud Run، وعمليات طلب البيانات من واجهات برمجة التطبيقات الخارجية لإنشاء تطبيقات مرنة للحوسبة بدون خادم.
وكما هو متوقّع من أداة تنظيم، تتيح لك Workflows تحديد سير عمل منطق نشاطك التجاري في لغة تعريف سير العمل المستندة إلى YAML/JSON، كما توفّر Workflows Execution API وواجهة مستخدم Workflows لتشغيل مهام سير العمل هذه.
وهو أكثر من مجرد أداة تنسيق، إذ يتضمّن الميزات المضمّنة والقابلة للضبط التالية:
- إعادة المحاولة المرنة ومعالجة الأخطاء بين الخطوات لتنفيذ الخطوات بشكل موثوق
- تحليل JSON وتمرير المتغيرات بين الخطوات لتجنُّب رمز الربط
- تسمح صيغ التعبيرات الخاصة بالقرارات بتنفيذ الخطوات الشرطية.
- عمليات سير العمل الفرعية لعمليات سير العمل النموذجية والقابلة لإعادة الاستخدام
- يتيح دعم الخدمات الخارجية تنسيق الخدمات خارج Google Cloud.
- إتاحة المصادقة لخدمات Google Cloud والخدمات الخارجية من أجل تنفيذ الخطوات بشكل آمن
- موصلات لخدمات Google Cloud، مثل Pub/Sub وFirestore و"مهام Google" وSecret Manager لتسهيل عملية التكامل
بالإضافة إلى ذلك، فإنّ Workflows هو منتج بدون خادم مُدار بالكامل. لا حاجة إلى إعداد الخوادم أو توسيع نطاقها، والدفع مقابل ما تستخدمه فقط.
4. تفعيل واجهات برمجة التطبيقات
في هذا التمرين العملي، ستربط بين خدمات Cloud Functions وCloud Run باستخدام Workflows. ستستخدم أيضًا App Engine وCloud Build وVision API وخدمات أخرى.
في Cloud Shell، تأكَّد من تفعيل جميع الخدمات اللازمة:
gcloud services enable \ appengine.googleapis.com \ cloudbuild.googleapis.com \ cloudfunctions.googleapis.com \ compute.googleapis.com \ firestore.googleapis.com \ run.googleapis.com \ vision.googleapis.com \ workflows.googleapis.com \
بعد مرور بعض الوقت، من المفترض أن تظهر لك رسالة تفيد بإتمام العملية بنجاح:
Operation "operations/acf.5c5ef4f6-f734-455d-b2f0-ee70b5a17322" finished successfully.
5- الحصول على الشفرة
احصل على الرمز إذا لم يسبق لك الحصول عليه في ورش العمل السابقة حول الرموز البرمجية:
git clone https://github.com/GoogleCloudPlatform/serverless-photosharing-workshop
ستتوفّر لك بنية المجلدات التالية ذات الصلة بهذا الدرس التطبيقي:
frontend | workflows | ├── functions ├── |── trigger-workflow ├── |── vision-data-transform ├── services ├── |── collage ├── |── thumbnails ├── workflows.yaml
في ما يلي المجلدات ذات الصلة:
- يحتوي
frontendعلى الواجهة الأمامية لخدمة App Engine التي سنعيد استخدامها من التمرين العملي 4. - يحتوي
functionsعلى دوال Cloud Functions التي تم إنشاؤها لسير العمل. - يحتوي
servicesعلى خدمات Cloud Run المعدَّلة لسير العمل. workflows.yamlهو ملف تعريف سير العمل.
6. استكشاف ملف YAML الخاص بـ Workflows
يحدّد الملف workflows.yaml سير العمل في سلسلة من الخطوات. لنستعرضها معًا لفهمها بشكل أفضل.
في بداية سير العمل، يتم تمرير بعض المَعلمات. سيتم تمريرها من خلال وظيفتَين في Cloud Functions تؤديان إلى تشغيل Workflows. سنتناول هذه الدوال لاحقًا، ولكن إليك طريقة بدء "مهام سير العمل":

في YAML، يمكنك ملاحظة أنّه يتم تعيين هذه المَعلمات للمتغيرات في الخطوة init، مثل أسماء الملفات والحِزم التي تؤدي إلى تشغيل الحدث، وعناوين URL لبعض خدمات Cloud Functions وCloud Run التي ستستدعيها Workflows:
main:
params: [args]
steps:
- init:
assign:
- file: ${args.file}
- bucket: ${args.bucket}
- gsUri: ${"gs://" + bucket + "/" + file}
- projectId: ${sys.get_env("GOOGLE_CLOUD_PROJECT_ID")}
- urls: ${args.urls}
بعد ذلك، تتحقّق "سير العمل" من نوع الحدث. يتوفّر نوعان من الأحداث: object.finalize (يتم إرساله عند حفظ ملف في حزمة التخزين السحابي) وobject.delete (يتم إرساله عند حذف ملف). سيؤدي أي شيء آخر إلى ظهور استثناء "الحدث غير متاح".

في ما يلي الخطوة التي نتحقّق فيها من نوع حدث تخزين الملفات في تعريف سير العمل بتنسيق YAML:
- eventTypeSwitch:
switch:
- condition: ${args.eventType == "google.storage.object.finalize"}
next: imageAnalysisCall
- condition: ${args.eventType == "google.storage.object.delete"}
next: pictureGarbageCollectionGCS
- eventTypeNotSupported:
raise: ${"eventType " + args.eventType + " is not supported"}
next: end
لاحظ كيف تتيح Workflows عبارات التبديل ومعالجة الاستثناءات، وذلك باستخدام تعليمات التبديل وشروطها المختلفة، وتعليمات رفع الخطأ عند عدم التعرّف على الحدث.
بعد ذلك، لنلقِ نظرة على imageAnalysisCall. هذه سلسلة من الطلبات من Workflows لاستدعاء Vision API من أجل تحليل الصورة وتحويل بيانات الردّ من Vision API لترتيب تصنيفات العناصر التي تم التعرّف عليها في الصورة واختيار الألوان السائدة والتحقّق مما إذا كانت الصورة آمنة للعرض، ثم حفظ البيانات الوصفية في Cloud Firestore.
يُرجى العلم أنّه يتم تنفيذ كل شيء في "مهام سير العمل" باستثناء "وظائف Vision Transform Cloud" (التي سننشرها لاحقًا):

في ما يلي شكل الخطوات بتنسيق YAML:
- imageAnalysisCall:
call: http.post
args:
url: https://vision.googleapis.com/v1/images:annotate
headers:
Content-Type: application/json
auth:
type: OAuth2
body:
requests:
- image:
source:
gcsImageUri: ${gsUri}
features:
- type: LABEL_DETECTION
- type: SAFE_SEARCH_DETECTION
- type: IMAGE_PROPERTIES
result: imageAnalysisResponse
- transformImageAnalysisData:
call: http.post
args:
url: ${urls.VISION_DATA_TRANSFORM_URL}
auth:
type: OIDC
body: ${imageAnalysisResponse.body}
result: imageMetadata
- checkSafety:
switch:
- condition: ${imageMetadata.body.safe == true}
next: storeMetadata
next: end
- storeMetadata:
call: http.request
args:
url: ${"https://firestore.googleapis.com/v1/projects/" + projectId + "/databases/(default)/documents/pictures/" + file + "?updateMask.fieldPaths=color&updateMask.fieldPaths=labels&updateMask.fieldPaths=created"}
auth:
type: OAuth2
method: PATCH
body:
name: ${"projects/" + projectId + "/databases/(default)/documents/pictures/" + file}
fields:
color:
stringValue: ${imageMetadata.body.color}
created:
timestampValue: ${imageMetadata.body.created}
labels:
arrayValue:
values: ${imageMetadata.body.labels}
result: storeMetadataResponse
بعد تحليل الصورة، تتمثل الخطوتان التاليتان في إنشاء صورة مصغّرة للصورة ومجموعة من أحدث الصور. يتم ذلك من خلال نشر خدمتَين على Cloud Run وإجراء طلبات إليهما من الخطوتَين thumbnailCall وcollageCall:

الخطوات في ملف YAML:
- thumbnailCall:
call: http.post
args:
url: ${urls.THUMBNAILS_URL}
auth:
type: OIDC
body:
gcsImageUri: ${gsUri}
result: thumbnailResponse
- collageCall:
call: http.get
args:
url: ${urls.COLLAGE_URL}
auth:
type: OIDC
result: collageResponse
ينتهي فرع التنفيذ هذا بعرض رموز الحالة من كل خدمة في الخطوة finalizeCompleted:
- finalizeCompleted:
return:
imageAnalysis: ${imageAnalysisResponse.code}
storeMetadata: ${storeMetadataResponse.code}
thumbnail: ${thumbnailResponse.code}
collage: ${collageResponse.code}
يحدث فرع التنفيذ الآخر عند حذف ملف من حزمة التخزين الرئيسية التي تحتوي على إصدارات الصور العالية الدقة. في هذا الفرع، نريد حذف الصورة المصغّرة من الحزمة التي تحتوي على الصور المصغّرة وحذف بياناتها الوصفية من Firestore. يتم تنفيذ كلتا العمليتين باستخدام طلبات HTTP من Workflows:

الخطوات في ملف YAML:
- pictureGarbageCollectionGCS:
try:
call: http.request
args:
url: ${"https://storage.googleapis.com/storage/v1/b/thumbnails-" + projectId + "/o/" + file}
auth:
type: OAuth2
method: DELETE
result: gcsDeletionResult
except:
as: e
steps:
- dummyResultInOutVar:
assign:
- gcsDeletionResult:
code: 200
body: "Workaround for empty body response"
- pictureGarbageCollectionFirestore:
call: http.request
args:
url: ${"https://firestore.googleapis.com/v1/projects/" + projectId + "/databases/(default)/documents/pictures/" + file}
auth:
type: OAuth2
method: DELETE
result: firestoreDeletionResult
ينتهي فرع الحذف بعرض النتائج أو الرموز من كل خطوة:
- deleteCompleted:
return:
gcsDeletion: ${gcsDeletionResult}
firestoreDeletion: ${firestoreDeletionResult.code}
في الخطوات التالية، سننشئ جميع التبعيات الخارجية لسير العمل: الحِزم وCloud Functions وخدمات Cloud Run وقاعدة بيانات Firestore.
7. إنشاء الحِزم
تحتاج إلى حزمتَين للصور: حزمة لحفظ الصور الأصلية العالية الدقة وحزمة لحفظ الصور المصغّرة.
أنشئ حزمة إقليمية (في هذه الحالة في أوروبا) متاحة للجميع مع إمكانية وصول موحّدة للمستخدمين لتحميل الصور باستخدام الأداة gsutil:
export BUCKET_PICTURES=uploaded-pictures-${GOOGLE_CLOUD_PROJECT}
gsutil mb -l EU gs://${BUCKET_PICTURES}
gsutil uniformbucketlevelaccess set on gs://${BUCKET_PICTURES}
gsutil iam ch allUsers:objectViewer gs://${BUCKET_PICTURES}
أنشئ حزمة إقليمية أخرى متاحة للجميع للصور المصغّرة:
export BUCKET_THUMBNAILS=thumbnails-${GOOGLE_CLOUD_PROJECT}
gsutil mb -l EU gs://${BUCKET_THUMBNAILS}
gsutil uniformbucketlevelaccess set on gs://${BUCKET_THUMBNAILS}
gsutil iam ch allUsers:objectViewer gs://${BUCKET_THUMBNAILS}
يمكنك التأكّد من إنشاء الحِزم وإتاحتها للجميع من خلال الانتقال إلى قسم Cloud Storage في Cloud Console:

8. تحويل بيانات Vision (دالة Cloud)
يبدأ ملف Workflows.yaml بالخطوات init وeventTypeSwitch وeventTypeNotSupported. تضمن هذه المعرّفات توجيه الأحداث الواردة من المجموعات إلى الخطوات الصحيحة.
بالنسبة إلى حدث object.finalize، تنفّذ الخطوة imageAnalysisCall طلبًا إلى Vision API لاستخراج البيانات الوصفية للصورة التي تم إنشاؤها. يتم تنفيذ جميع هذه الخطوات ضمن "مهام سير العمل" على النحو التالي:

بعد ذلك، علينا تحويل البيانات التي تم إرجاعها من Vision API قبل أن نتمكّن من حفظها في Firestore. على وجه التحديد، علينا:
- تعرض هذه السمة قائمة بالتصنيفات التي تم إرجاعها للصورة.
- استرداد اللون السائد في الصورة
- تحديد ما إذا كانت الصورة آمنة
يتم ذلك في الرمز البرمجي في Cloud Function، وتستدعي Workflows هذه الدالة ببساطة:

استكشاف الرمز
يُطلق على Cloud Function اسم vision-data-transform. يمكنك الاطّلاع على الرمز الكامل في index.js. كما ترى، الغرض الوحيد من هذه الدالة هو تحويل JSON إلى JSON، وذلك لتخزين البيانات الوصفية للصور بسهولة في Firestore.
النشر على Cloud Functions
انتقِل إلى المجلد:
cd workflows/functions/vision-data-transform/nodejs
حدِّد المنطقة التي تريدها:
export REGION=europe-west1
gcloud config set functions/region ${REGION}
يمكنك نشر الدالة باستخدام الأمر التالي:
export SERVICE_NAME=vision-data-transform
gcloud functions deploy ${SERVICE_NAME} \
--source=. \
--runtime nodejs10 \
--entry-point=vision_data_transform \
--trigger-http \
--allow-unauthenticated
بعد نشر الدالة، ستتمكّن خطوة transformImageAnalysisData في Workflows من استدعاء هذه الدالة لإجراء عملية تحويل البيانات في Vision API.
9. إعداد قاعدة البيانات
بعد ذلك، في "سير العمل"، يتم التحقّق من أمان الصورة من بيانات الصورة، ثم يتم تخزين المعلومات حول الصورة التي تعرضها Vision API في قاعدة بيانات Cloud Firestore، وهي قاعدة بيانات مستنِدة إلى مستندات NoSQL سريعة ومُدارة بالكامل وبدون خادم ومستنِدة إلى السحابة الإلكترونية:

يتم تنفيذ كلتا العمليتين في "مهام سير العمل"، ولكن عليك إنشاء قاعدة بيانات Firestore لكي تعمل عملية تخزين البيانات الوصفية.
أولاً، أنشئ تطبيق App Engine في المنطقة التي تريد إنشاء قاعدة بيانات Firestore فيها (وهذا شرط لاستخدام Firestore):
export REGION_FIRESTORE=europe-west2
gcloud app create --region=${REGION_FIRESTORE}
بعد ذلك، أنشئ قاعدة بيانات Firestore في المنطقة نفسها:
gcloud firestore databases create --region=${REGION_FIRESTORE}
سيتم إنشاء المستندات آليًا في مجموعتنا وستحتوي على 4 حقول:
- name (سلسلة): اسم ملف الصورة التي تم تحميلها، وهو أيضًا مفتاح المستند
- labels (مصفوفة من السلاسل): تصنيفات العناصر التي تتعرّف عليها Vision API
- اللون (سلسلة): رمز اللون السداسي العشري للون السائد (مثلاً #ab12ef)
- created (التاريخ): الطابع الزمني لوقت تخزين البيانات الوصفية لهذه الصورة
- thumbnail (قيمة منطقية): حقل اختياري سيتم عرضه وتكون قيمته "صحيح" إذا تم إنشاء صورة مصغّرة لهذه الصورة
بما أنّنا سنبحث في Firestore للعثور على صور تتضمّن صورًا مصغّرة متاحة، وسنرتبها حسب تاريخ الإنشاء، علينا إنشاء فهرس بحث. يمكنك إنشاء الفهرس باستخدام الأمر التالي:
gcloud firestore indexes composite create --collection-group=pictures \ --field-config field-path=thumbnail,order=descending \ --field-config field-path=created,order=descending
يُرجى العِلم أنّ إنشاء الفهرس قد يستغرق 10 دقائق أو أكثر.
بعد إنشاء الفهرس، يمكنك الاطّلاع عليه في Cloud Console:

ستتمكّن خطوة storeMetadata في سير العمل الآن من تخزين البيانات الوصفية للصور في Firestore.
10. خدمة الصور المصغّرة (Cloud Run)
الخطوة التالية في السلسلة هي إنشاء صورة مصغّرة. يتم ذلك في الرمز البرمجي في إحدى خدمات Cloud Run، وتطلب "مهام سير العمل" هذه الخدمة في الخطوة thumbnailCall:

استكشاف الرمز
اسم خدمة Cloud Run هو thumbnails. يمكنك الاطّلاع على الرمز الكامل في index.js.
إنشاء صورة الحاوية ونشرها
تتيح خدمة Cloud Run تشغيل الحاويات، ولكن عليك أولاً إنشاء صورة الحاوية (المحدّدة في Dockerfile). ويمكن استخدام Google Cloud Build لإنشاء صور الحاويات ثم استضافتها في Google Container Registry.
انتقِل إلى المجلد:
cd workflows/services/thumbnails/nodejs
الإصدار:
export SERVICE_SRC=thumbnails
export SERVICE_NAME=${SERVICE_SRC}-service
gcloud builds submit \
. \
--tag gcr.io/${GOOGLE_CLOUD_PROJECT}/${SERVICE_NAME}
بعد دقيقة أو دقيقتين، من المفترض أن تنجح عملية الإنشاء وسيتم نشر الحاوية في Google Container Registry.
النشر على Cloud Run
اضبط بعض المتغيّرات والإعدادات اللازمة:
export BUCKET_THUMBNAILS=thumbnails-${GOOGLE_CLOUD_PROJECT}
export REGION=europe-west1
gcloud config set run/region ${REGION}
gcloud config set run/platform managed
يمكنك نشر التطبيق باستخدام الأمر التالي:
gcloud run deploy ${SERVICE_NAME} \
--image gcr.io/${GOOGLE_CLOUD_PROJECT}/${SERVICE_NAME} \
--no-allow-unauthenticated \
--memory=1Gi \
--update-env-vars BUCKET_THUMBNAILS=${BUCKET_THUMBNAILS}
بعد نشر الخدمة، ستتمكّن خطوة Workflows thumbnailCall من استدعاء هذه الخدمة.
11. خدمة الصور المجمّعة (Cloud Run)
الخطوة التالية هي إنشاء صورة مجمّعة من أحدث الصور. يتم ذلك في الرمز البرمجي في إحدى خدمات Cloud Run، وتطلب Workflows هذه الخدمة في الخطوة collageCall:

استكشاف الرمز
اسم خدمة Cloud Run هو collage. يمكنك الاطّلاع على الرمز الكامل في index.js.
إنشاء صورة الحاوية ونشرها
تتيح خدمة Cloud Run تشغيل الحاويات، ولكن عليك أولاً إنشاء صورة الحاوية (المحدّدة في Dockerfile). ويمكن استخدام Google Cloud Build لإنشاء صور الحاويات ثم استضافتها في Google Container Registry.
انتقِل إلى المجلد:
cd services/collage/nodejs
الإصدار:
export SERVICE_SRC=collage
export SERVICE_NAME=${SERVICE_SRC}-service
gcloud builds submit \
. \
--tag gcr.io/${GOOGLE_CLOUD_PROJECT}/${SERVICE_NAME}
بعد دقيقة أو دقيقتين، من المفترض أن تنجح عملية الإنشاء وسيتم نشر الحاوية في Google Container Registry.
النشر على Cloud Run
اضبط بعض المتغيّرات والإعدادات اللازمة:
export BUCKET_THUMBNAILS=thumbnails-${GOOGLE_CLOUD_PROJECT}
export REGION=europe-west1
gcloud config set run/region ${REGION}
gcloud config set run/platform managed
النشر:
gcloud run deploy ${SERVICE_NAME} \
--image gcr.io/${GOOGLE_CLOUD_PROJECT}/${SERVICE_NAME} \
--no-allow-unauthenticated \
--memory=1Gi \
--update-env-vars BUCKET_THUMBNAILS=${BUCKET_THUMBNAILS}
بعد نشر الخدمة، يمكنك التحقّق من أنّ كلتا الخدمتين تعملان ضمن قسم Cloud Run في Cloud Console، وستتمكّن الخطوة collageCall في Workflows من استدعاء هذه الخدمة:

12. نشر مهام سير العمل
لقد نشرنا جميع التبعيات الخارجية لـ "مهام سير العمل". يمكن إكمال جميع الخطوات المتبقية (finalizeCompleted وpictureGarbageCollectionGCS وpictureGarbageCollectionFirestore وdeleteCompleted) من خلال Workflows نفسه.
حان وقت نشر سير العمل.
انتقِل إلى المجلد الذي يحتوي على ملف workflows.yaml ونفِّذه باستخدام:
export WORKFLOW_REGION=europe-west4
export WORKFLOW_NAME=picadaily-workflows
gcloud workflows deploy ${WORKFLOW_NAME} \
--source=workflows.yaml \
--location=${WORKFLOW_REGION}
في غضون ثوانٍ قليلة، من المفترض أن يتم نشر سير العمل ويمكنك الاطّلاع عليه في قسم "سير العمل" في Cloud Console:

يمكنك النقر على سير العمل وتعديله إذا أردت. أثناء التعديل، ستحصل على تمثيل مرئي جميل لسير العمل:

يمكنك أيضًا تنفيذ سير العمل من Cloud Console يدويًا باستخدام المَعلمات الصحيحة. بدلاً من ذلك، سننفّذها تلقائيًا استجابةً لأحداث Cloud Storage في الخطوة التالية.
13. مشغّلات Workflows (Cloud Functions)
تم نشر سير العمل وأصبح جاهزًا. الآن، علينا تشغيل "سير العمل" عند إنشاء ملف أو حذفه في حزمة Cloud Storage. هذه هي أحداث storage.object.finalize وstorage.object.delete على التوالي.
تتضمّن Workflows واجهات برمجة تطبيقات ومكتبات برامج لإنشاء Workflows وإدارتها وتنفيذها. في هذه الحالة، ستستخدم Workflows Execution API، وتحديدًا مكتبة عميل Node.js لتشغيل سير العمل.
سيتم تفعيل Workflows من Cloud Function التي تستمع إلى أحداث Cloud Storage. بما أنّ Cloud Function يمكنها الاستماع إلى نوع حدث واحد فقط، عليك نشر وظيفتَين من Cloud Functions للاستماع إلى أحداث الإنشاء والحذف:

استكشاف الرمز
يُطلق على Cloud Function اسم trigger-workflow. يمكنك الاطّلاع على الرمز الكامل في index.js.
النشر على Cloud Functions
انتقِل إلى المجلد:
cd workflows/functions/trigger-workflow/nodejs
اضبط بعض المتغيّرات والإعدادات اللازمة:
export BUCKET_PICTURES=uploaded-pictures-${GOOGLE_CLOUD_PROJECT}
export REGION=europe-west1
export WORKFLOW_NAME=picadaily-workflows
export WORKFLOW_REGION=europe-west4
export COLLAGE_URL=$(gcloud run services describe collage-service --format 'value(status.url)')
export THUMBNAILS_URL=$(gcloud run services describe thumbnails-service --format 'value(status.url)')
export VISION_DATA_TRANSFORM_URL=$(gcloud functions describe vision-data-transform --format 'value(httpsTrigger.url)')
gcloud config set functions/region ${REGION}
نشر الدالة التي تستجيب لأحداث الإنهاء:
export SERVICE_NAME=trigger-workflow-on-finalize
gcloud functions deploy ${SERVICE_NAME} \
--source=. \
--runtime nodejs10 \
--entry-point=trigger_workflow \
--trigger-resource=${BUCKET_PICTURES} \
--trigger-event=google.storage.object.finalize \
--allow-unauthenticated \
--set-env-vars GOOGLE_CLOUD_PROJECT=${GOOGLE_CLOUD_PROJECT},WORKFLOW_REGION=${WORKFLOW_REGION},WORKFLOW_NAME=${WORKFLOW_NAME},THUMBNAILS_URL=${THUMBNAILS_URL},COLLAGE_URL=${COLLAGE_URL},VISION_DATA_TRANSFORM_URL=${VISION_DATA_TRANSFORM_URL}
انشر الدالة الثانية التي تستجيب لأحداث الحذف:
export SERVICE_NAME=trigger-workflow-on-delete
gcloud functions deploy ${SERVICE_NAME} \
--source=. \
--runtime nodejs10 \
--entry-point=trigger_workflow \
--trigger-resource=${BUCKET_PICTURES} \
--trigger-event=google.storage.object.delete \
--allow-unauthenticated \
--set-env-vars GOOGLE_CLOUD_PROJECT=${GOOGLE_CLOUD_PROJECT},WORKFLOW_REGION=${WORKFLOW_REGION},WORKFLOW_NAME=${WORKFLOW_NAME},THUMBNAILS_URL=${THUMBNAILS_URL},COLLAGE_URL=${COLLAGE_URL},VISION_DATA_TRANSFORM_URL=${VISION_DATA_TRANSFORM_URL}
عند اكتمال عملية النشر، يمكنك الاطّلاع على كلتا الدالتين في Cloud Console:

14. الواجهة الأمامية (App Engine)
في هذه الخطوة، يمكنك إنشاء واجهة أمامية للويب على Google App Engine من Pic-a-daily: الميزة الاختبارية 4 — إنشاء واجهة أمامية للويب تتيح للمستخدمين تحميل الصور من تطبيق الويب، بالإضافة إلى تصفّح الصور المحمَّلة وصورها المصغّرة.

يمكنك التعرّف على مزيد من المعلومات عن App Engine وقراءة وصف الرمز البرمجي في Pic-a-daily: الميزة الاختبارية 4 — إنشاء واجهة أمامية للويب.
استكشاف الرمز
اسم تطبيق App Engine هو frontend. يمكنك الاطّلاع على الرمز الكامل في index.js.
النشر على App Engine
انتقِل إلى المجلد:
cd frontend
اضبط المنطقة التي تختارها واستبدِل أيضًا GOOGLE_CLOUD_PROJECT في ملف app.yaml برقم تعريف مشروعك الفعلي:
export REGION=europe-west1
gcloud config set compute/region ${REGION}
sed -i -e "s/GOOGLE_CLOUD_PROJECT/${GOOGLE_CLOUD_PROJECT}/" app.yaml
النشر:
gcloud app deploy app.yaml -q
بعد دقيقة أو دقيقتَين، سيتم إعلامك بأنّ التطبيق يعرض عددًا كبيرًا من الزيارات:
Beginning deployment of service [default]... ╔════════════════════════════════════════════════════════════╗ ╠═ Uploading 8 files to Google Cloud Storage ═╣ ╚════════════════════════════════════════════════════════════╝ File upload done. Updating service [default]...done. Setting traffic split for service [default]...done. Deployed service [default] to [https://GOOGLE_CLOUD_PROJECT.appspot.com] You can stream logs from the command line by running: $ gcloud app logs tail -s default To view your application in the web browser run: $ gcloud app browse
يمكنك أيضًا الانتقال إلى قسم App Engine في Cloud Console للتأكّد من نشر التطبيق واستكشاف ميزات App Engine، مثل التحكم في الإصدارات وتقسيم الزيارات:

15. اختبار مهام سير العمل
للاختبار، انتقِل إلى عنوان URL التلقائي لتطبيق App Engine (https://<YOUR_PROJECT_ID>.appspot.com/) ويجب أن ترى واجهة المستخدم الأمامية تعمل.

حمِّل صورة. من المفترض أن يؤدي ذلك إلى تشغيل سير العمل، ويمكنك الاطّلاع على تنفيذ سير العمل في الحالة Active في Cloud Console:

بعد اكتمال "سير العمل"، يمكنك النقر على رقم تعريف التنفيذ والاطّلاع على الناتج من الخدمات المختلفة:

حمِّل 3 صور أخرى. من المفترض أن تظهر لك أيضًا الصورة المصغّرة وتجميع الصور في حِزم Cloud Storage وواجهة App Engine الأمامية المعدَّلة:

16. التنظيف (اختياري)
إذا لم تكن تنوي الاحتفاظ بالتطبيق، يمكنك تنظيف الموارد لتوفير التكاليف ولتكون مواطنًا جيدًا للخدمات السحابية بشكل عام من خلال حذف المشروع بأكمله:
gcloud projects delete ${GOOGLE_CLOUD_PROJECT}
17. تهانينا!
لقد أنشأت نسخة منظَّمة من التطبيق باستخدام Workflows لتنظيم الخدمات واستدعائها.
المواضيع التي تناولناها
- App Engine
- Cloud Firestore
- وظائف السحابة الإلكترونية
- Cloud Run
- Workflows