ייצוא לאחסון אובייקטים

אובייקט JSON אחד לכל יעד שהושג, ב-bucket שבבעלותך. זהו הנתיב לכל מחסן נתונים שאינו BigQuery.

1. הפער שהגשר ממלא

עד כה הייתה בדיוק דרך אחת מ-MousePlayer למחסן נתונים, והיא הובילה ל-Google. למי שמפעיל Snowflake, Redshift או ClickHouse לא הייתה דרך — אף ששלושתם קוראים מאחסון אובייקטים ללא קושי.

לכן הגשר כותב לאחסון אובייקטים במקום לכל מחסן נתונים בנפרד. Snowflake קולטת מ-S3, Redshift קולטת מ-S3, ClickHouse קולטת מ-S3 ו-BigQuery קולטת מ-Google Cloud Storage. ייצוא אחד מגיע לכולם.

לאןכיצד פונים אליו
Amazon S3Signature Version 4, עם ה-bucket בשם המארח
Cloudflare R2Signature Version 4 מול נקודת הקצה של החשבון שלך
Google Cloud Storageדרך API תואם S3, עם מפתח HMAC
MinIO, Wasabi, Backblaze B2 ואחריםSignature Version 4 מול נקודת הקצה שלך
Azure Blob Storageקישור SAS למכולה — ללא חתימה בצד שלנו כלל

2. מדוע Azure שונה, ולמה זה עדיף

Azure Blob אינו משתמש ב-Signature Version 4; הוא חותם ב-SharedKey. יכולנו לבנות מנגנון חתימה שני. במקום זאת הגשר מקבל קישור SAS למכולה — URL שנוצר בחשבון האחסון שלך ושהחתימה כבר כלולה בו.

כך יש פחות קוד בצד שלנו ופחות אמון נדרש מצדך. לעולם איננו רואים מפתח חשבון: מה שנמסר הוא הרשאה שהוגבלה על ידך למכולה אחת, עם תאריך תפוגה שבחרת ואפשרות ביטול בכל עת ללא שינוי בדבר אחר.

כדאי להחיל אותה הגבלה גם בצד S3: להעניק למפתח הגישה הרשאת כתיבה רק אל קידומת יחידה זו ולא לשום דבר אחר. מפתח שיכול רק להוסיף אל mouseplayer/goals/ אינו יכול לקרוא buckets אחרים גם אם ידלוף.

3. אובייקט אחד לכל יעד, והמפתח הוא תאריך

באחסון אובייקטים אין פעולת הוספה לסוף. קובץ יומי היה דורש כתיבה מחדש בכל פעם, ושני יעדים שמגיעים יחד היו דורסים זה את זה. לכן כל יעד שהושג הופך לאובייקט משלו.

המחיר הוא ריבוי אובייקטים קטנים; מבנה המפתח הוא שמאפשר זאת:

prefix/YYYY/MM/DD/channel/session-goal.json

מחסן נתונים קורא יום אחד כמחיצה אחת, והשלמת נתוני עבר היא סריקת קידומת במקום שאילתה. לחלוקה לפי פרויקט במקום לפי תאריך, יש להוסיף את מזהה הערוץ לקידומת.

כל אובייקט הוא שורת JSON אחת

ללא הזחה במכוון, כך שקידומת שלמה נקראת כ-NDJSON בלי לפתוח כל אובייקט בנפרד. חותמת זמן, פרויקט, סשן, מזהה לקוח, יעד, ערך, מטבע וקישור לניגון ההקלטה.

ערך ריק הוא null, לא אפס

יעד ללא ערך כספי כותב null. במחסן נתונים, אפס היה מצטרף לסכום שמעולם לא התקיים — ההבחנה בין “לא הוגדר סכום” לבין “סכום של אפס” נשמרת בייצוא.

4. אם מתקבלת תשובת 403, כדאי לקרוא זאת תחילה

בקשת S3 שנדחתה כמעט אינה מסבירה דבר, ויש סיבה לכך שהודעת השגיאה ביומן שלנו אומרת יותר מזו של S3: האזור נכלל בחתימה. אזור שגוי ומפתח שגוי יוצרים אותו 403, ולכן החשד המתבקש — המפתח — נכון רק במחצית המקרים.

שלושה דברים לבדיקה, בסדר הזה:

  • האזור, בדיוק כפי שה-bucket מציין אותו. R2 ו-Google Cloud Storage מקבלים auto ואינם בודקים אותו; כל האחרים כן.
  • הרשאת הקידומת. מפתח שמוגבל אל mouseplayer/ אינו יכול לכתוב אל mouseplayer-goals/ — הלוכסן בסוף חשוב ב-ARN של משאב.
  • נקודת הקצה, עבור R2 ואחסון תואם S3. יש להדביק את שם המארח ללא https://; אנו מסירים את התחילית בכל מקרה, אך נתיב שמתווסף אחריה מציין bucket אחר.

מזהה מפתח הגישה נשמר ללא הצפנה במכוון. הוא נשלח בכל בקשה חתומה כחלק מהתכנון, ולכן הצפנתו הייתה מאמץ ללא הגנה. הסוד מוצפן, לעולם אינו מוצג שוב ולעולם אינו נכנס לתור הפנימי שנושא את המשימה.

כל הסימנים המסחריים המוזכרים כאן שייכים לבעליהם בהתאמה. ל-MousePlayer אין קשר עסקי עם ספקים אלה.