לדלג לתוכן

מקורות Node ו-Python

לפעמים הנתונים שאתם צריכים נמצאים מאחורי קוד שהצוות שלכם כבר כתב: מודל ניקוד, לקוח לשירות פנימי, סקריפט שמסדר ייצוא. מקור Node או Python מאפשר להגיש את הקוד הזה כטבלאות. אתם מסמנים את הפונקציות שרוצים לשתף, מפנים את Provisa אל הקוד, וכל פונקציה מסומנת הופכת לטבלה שכל תפקיד קורא לפי אותם כללים כמו כל טבלה אחרת.

למה הופכת פונקציה

Provisa קורא את ההצהרות של הקוד עצמו: תגי JSDoc וטיפוסי TypeScript ב-Node, docstrings ורמזי טיפוס ב-Python. שלושה תגים נחשבים.

תג הופך ל
@table טבלה. הפונקציה מחזירה רשימה או אובייקט איטרבילי, וכל איבר הוא שורה
@command Command, שרץ לפי בקשה
@stream טבלה חיה. הפונקציה היא גנרטור, וכל שורה נשלחת ברגע שהיא מופקת

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

טיפוס השורה קובע את העמודות. טקסט, מספרים, בוליאנים, תאריכים וחותמות זמן ממופים לטיפוסי העמודות שלהם, רשימות נשארות רשימות, ואובייקטים מקוננים הופכים לטיפוסים בעלי שם. כשטיפוס השורה רופף (any, unknown או Record ב-TypeScript, Any או dict ב-Python), Provisa קורא לפונקציה פעם אחת, בלי ארגומנטים, ומציע עמודות לפי השורות שחוזרות. אם לפונקציה יש פרמטר חובה אי אפשר לקרוא לה כך, ואתם קובעים את טיפוסי העמודות בעצמכם כשאתם רושמים את הטבלה.

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

מאיפה הקוד מגיע

הקוד מקובע, כך שמקור תמיד מריץ בדיוק את מה שנרשם:

  • חבילה: חבילת npm ל-Node או חבילת PyPI ל-Python, בגרסה מדויקת.
  • מאגר Git: commit מלא בן 40 תווים, עם תת-תיקייה אם הקוד לא נמצא בשורש.
  • העלאה: קובץ .zip, .tgz או .tar.gz של הקוד.

קוד Node רץ על Node.js, Bun או Deno, לפי בחירתכם. קוד Python רץ על ה-Python ש-Provisa מספק. כשיש לקוד יותר ממודול Python אחד ברמה העליונה, ציינו בשדה מודול כניסה דרך איזה מהם נכנסים.

התקנת תלויות

קוד עם תלויות צריך lockfile, וכל התקנה עוקבת אחריו בדיוק. בלעדיו, חבילה שמצהירה על תלויות נדחית, והדחייה אומרת לכם להוסיף אחד.

סביבת ריצה Lockfile
Node.js package-lock.json או npm-shrinkwrap.json
Bun bun.lock או bun.lockb
Deno deno.lock
Python uv.lock (עם ה-pyproject.toml שלו), pylock.toml, או requirements.txt עם --hash בכל שורה

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

אף חבילה לא מורשית להריץ סקריפטי התקנה משלה: npm מתקין עם --ignore-scripts, ו-Python מתקין רק wheels ולעולם לא בונה מהפצת קוד מקור.

החבילות מגיעות ממאגרי החבילות של הארגון שלכם, אם יש לכם כאלה. מנהל מזין פעם אחת את מאגרי ה-npm, אינדקסי ה-PyPI ושרתי ה-Git שלכם תחת Admin → מאגרי חבילות, וכל מקור Node ו-Python בארגון מתקין דרכם. מאגר ה-npm הציבורי וה-PyPI הציבורי לא צריכים רשומה. ראו מאגרי חבילות.

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

ארגז החול

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

קריאת טבלה

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

ארגומנטים מעבירים כמו כל פרמטר של טבלה: כתנאי _nf_ ב-SQL וכארגומנטים של שדה ב-GraphQL.

דוגמה

מודול ה-Python הזה מעריך עד כמה סביר שחשבון יעזוב:

from dataclasses import dataclass
from datetime import datetime


@dataclass
class RiskRow:
    account_id: str
    score: float
    computed_at: datetime
    reasons: list[str]


def churn_risk(account_id: str, as_of: datetime | None = None) -> list[RiskRow]:
    """Churn risk of one account.

    @table
    """
    ...

רשמו אותו כמקור python מחבילת ה-PyPI שלו, מ-commit ב-Git או מהעלאה. הגילוי מציע אז את churn_risk כטבלה עם ארבע עמודות (account_id, score, computed_at, reasons), פרמטר חובה account_id ופרמטר אופציונלי, as_of. אחרי ש-Steward רושם את הטבלה, קראו אותה ב-SQL:

SELECT score, reasons
FROM churn_risk
WHERE _nf_account_id = 'A-1042'

אותה פונקציה ב-TypeScript נראית כך:

export interface RiskRow {
  account_id: string;
  score: number;
  computed_at: Date;
  reasons: string[];
}

/** Churn risk of one account.
 * @table
 */
export async function churnRisk(accountId: string, asOf?: Date): Promise<RiskRow[]> {
  // ...
}