|
| 1 | +// Reservation references |
| 2 | +const RESERVATIONS = { |
| 3 | + HIGH_SLOTS: 'projects/httparchive/locations/US/reservations/pipeline', |
| 4 | + LOW_SLOTS: null, |
| 5 | + ON_DEMAND: 'none', |
| 6 | + DEFAULT: null |
| 7 | +} |
| 8 | + |
| 9 | +// Configuration for actions (JSON format for dynamic injection) |
| 10 | +const RESERVATION_CONFIG = { |
| 11 | + 'highSlots': [ |
| 12 | + 'httparchive.crawl.pages', |
| 13 | + 'httparchive.crawl.requests', |
| 14 | + 'httparchive.crawl.parsed_css', |
| 15 | + 'httparchive.f1.pages_latest', |
| 16 | + 'httparchive.f1.requests_latest' |
| 17 | + ], |
| 18 | + 'lowSlots': [], |
| 19 | + 'onDemand': [ |
| 20 | + 'httparchive.dataform_assertions.corrupted_technology_values' |
| 21 | + ] |
| 22 | +} |
| 23 | + |
| 24 | +// Convert arrays to Sets for O(1) lookup performance |
| 25 | +const RESERVATION_SETS = { |
| 26 | + highSlots: new Set(RESERVATION_CONFIG.highSlots), |
| 27 | + lowSlots: new Set(RESERVATION_CONFIG.lowSlots), |
| 28 | + onDemand: new Set(RESERVATION_CONFIG.onDemand) |
| 29 | +} |
| 30 | + |
| 31 | +/** |
| 32 | + * Determines the appropriate reservation for a given action name |
| 33 | + * @param {string} actionName - The fully qualified table name (with or without backticks) |
| 34 | + * @returns {string|null} The reservation identifier or null if no reservation assignment needed |
| 35 | + */ |
| 36 | +function getReservation(actionName) { |
| 37 | + if (!actionName || typeof actionName !== 'string') { |
| 38 | + return RESERVATIONS.DEFAULT |
| 39 | + } |
| 40 | + |
| 41 | + // Strip backticks if present and normalize |
| 42 | + const normalizedName = actionName.replace(/`/g, '').trim() |
| 43 | + |
| 44 | + if (RESERVATION_SETS.highSlots.has(normalizedName)) { |
| 45 | + return RESERVATIONS.HIGH_SLOTS |
| 46 | + } else if (RESERVATION_SETS.lowSlots.has(normalizedName)) { |
| 47 | + return RESERVATIONS.LOW_SLOTS |
| 48 | + } else if (RESERVATION_SETS.onDemand.has(normalizedName)) { |
| 49 | + return RESERVATIONS.ON_DEMAND |
| 50 | + } else { |
| 51 | + return RESERVATIONS.DEFAULT |
| 52 | + } |
| 53 | +} |
| 54 | + |
| 55 | +/** |
| 56 | + * Extracts action name from Dataform context object |
| 57 | + * @param {Object} ctx - Dataform context object |
| 58 | + * @returns {string|null} The extracted action name or null if not found |
| 59 | + */ |
| 60 | +function extractActionName(ctx) { |
| 61 | + if (!ctx) { |
| 62 | + return null |
| 63 | + } |
| 64 | + |
| 65 | + // Try primary method: ctx.self() |
| 66 | + if (typeof ctx.self === 'function') { |
| 67 | + const selfName = ctx.self() |
| 68 | + if (selfName) { |
| 69 | + return selfName |
| 70 | + } |
| 71 | + } |
| 72 | + |
| 73 | + // Fallback: construct from proto target |
| 74 | + if (ctx?.operation?.proto?.target) { |
| 75 | + const operationTarget = ctx?.operation?.proto?.target |
| 76 | + const parts = [] |
| 77 | + |
| 78 | + if (operationTarget.database) parts.push(operationTarget.database) |
| 79 | + if (operationTarget.schema) parts.push(operationTarget.schema) |
| 80 | + if (operationTarget.name) parts.push(operationTarget.name) |
| 81 | + |
| 82 | + return parts.length > 0 ? parts.join('.') : null |
| 83 | + } |
| 84 | + |
| 85 | + return null |
| 86 | +} |
| 87 | + |
| 88 | +/** |
| 89 | + * Generates the reservation SQL statement for a given Dataform context |
| 90 | + * @param {Object} ctx - Dataform context object with self() method and/or proto.target |
| 91 | + * @returns {string} The SQL statement to set reservation or empty string |
| 92 | + */ |
| 93 | +function reservation_setter(ctx) { |
| 94 | + const actionName = extractActionName(ctx) |
| 95 | + const reservation = getReservation(actionName) |
| 96 | + return reservation ? `SET @@RESERVATION='${reservation}';` : '' |
| 97 | +} |
| 98 | + |
| 99 | +module.exports = { |
| 100 | + reservation_setter |
| 101 | +} |
0 commit comments