(opts: {
serviceName: string;
cronEntrypoint: string;
handlerFunction?: string;
pythonBin: string;
env: NodeJS.ProcessEnv;
workPath: string;
})
| 120 | } |
| 121 | |
| 122 | async function getServiceCronsDynamic(opts: { |
| 123 | serviceName: string; |
| 124 | cronEntrypoint: string; |
| 125 | handlerFunction?: string; |
| 126 | pythonBin: string; |
| 127 | env: NodeJS.ProcessEnv; |
| 128 | workPath: string; |
| 129 | }): Promise<ServiceCronEntry[]> { |
| 130 | const { |
| 131 | serviceName, |
| 132 | cronEntrypoint, |
| 133 | handlerFunction, |
| 134 | pythonBin, |
| 135 | env, |
| 136 | workPath, |
| 137 | } = opts; |
| 138 | |
| 139 | if (!handlerFunction) { |
| 140 | throw new NowBuildError({ |
| 141 | code: 'PYTHON_DYNAMIC_CRON_NO_HANDLER', |
| 142 | message: |
| 143 | 'Dynamic cron detection requires a "module:object" entrypoint where the object has a get_crons() method.', |
| 144 | }); |
| 145 | } |
| 146 | |
| 147 | const moduleName = entrypointToModule(cronEntrypoint); |
| 148 | |
| 149 | const entries = await detectDynamicCrons({ |
| 150 | pythonBin, |
| 151 | env, |
| 152 | workPath, |
| 153 | moduleName, |
| 154 | attrName: handlerFunction, |
| 155 | }); |
| 156 | |
| 157 | console.log( |
| 158 | `Detected ${entries.length} cron entry(s): ${entries.map(e => `${e.module_function} (${e.schedule})`).join(', ')}` |
| 159 | ); |
| 160 | |
| 161 | if (entries.length === 0) { |
| 162 | throw new NowBuildError({ |
| 163 | code: 'PYTHON_DYNAMIC_CRON_EMPTY', |
| 164 | message: |
| 165 | `Dynamic cron detection returned no entries. ` + |
| 166 | `"${moduleName}.${handlerFunction}.get_crons()" returned an empty iterable.`, |
| 167 | }); |
| 168 | } |
| 169 | |
| 170 | return entries.map(entry => { |
| 171 | const cronPath = moduleColonFuncToCronPath( |
| 172 | serviceName, |
| 173 | entry.module_function |
| 174 | ); |
| 175 | return { |
| 176 | path: cronPath, |
| 177 | schedule: entry.schedule, |
| 178 | resolvedHandler: entry.module_function, |
| 179 | }; |
no test coverage detected