|
2 | 2 | # Licensed under the MIT License. |
3 | 3 |
|
4 | 4 | import asyncio |
| 5 | +import importlib |
5 | 6 | import logging |
6 | 7 | import os |
7 | 8 | import queue |
|
11 | 12 | import typing |
12 | 13 | from asyncio import AbstractEventLoop |
13 | 14 | from dataclasses import dataclass |
| 15 | +from importlib.metadata import entry_points |
14 | 16 | from typing import Any, Optional |
15 | 17 |
|
16 | 18 | import grpc |
17 | | -import importlib |
18 | 19 |
|
19 | 20 | from proxy_worker import protos |
20 | 21 | from proxy_worker.logging import ( |
@@ -422,112 +423,92 @@ def reload_library_worker(directory: str): |
422 | 423 | Load the appropriate runtime using the base package pattern. |
423 | 424 |
|
424 | 425 | This uses the runtime base package to automatically discover which |
425 | | - runtime is loaded. Runtimes auto-register via metaclass when imported. |
| 426 | + runtime is loaded. |
| 427 | +
|
| 428 | + If no runtime is registered via the base package, it falls back to |
| 429 | + the traditional detection method. |
426 | 430 | """ |
427 | 431 | global _library_worker, _library_worker_has_cv |
428 | 432 |
|
429 | | - try: |
430 | | - # Import runtime base package |
431 | | - from importlib.metadata import entry_points |
432 | | - import azurefunctions.extensions.base as runtime_base |
| 433 | + # Import base package |
| 434 | + import azurefunctions.extensions.base as runtime_base |
433 | 435 |
|
434 | | - # Discover all installed runtime packages via entry points |
435 | | - available_runtimes = entry_points(group='azurefunctions.runtimes') |
| 436 | + # Discover all installed runtime packages via entry points |
| 437 | + available_runtimes = entry_points(group='azurefunctions.runtimes') |
436 | 438 |
|
437 | | - for ep in available_runtimes: |
438 | | - try: |
439 | | - # Load the entry point (triggers import and |
440 | | - # metaclass registration) |
441 | | - ep.load() |
442 | | - logger.debug(f"Loaded runtime entry point: {ep.name}") |
443 | | - except Exception as e: |
444 | | - logger.debug(f"Could not load runtime {ep.name}: {e}") |
445 | | - continue |
446 | | - |
447 | | - # Check if a runtime was registered |
448 | | - if runtime_base.RuntimeFeatureChecker.runtime_loaded(): |
449 | | - # Get the registered runtime module |
450 | | - # (e.g., "azure_functions_fastapi.runtime") |
451 | | - runtime_module_name = ( |
452 | | - runtime_base.RuntimeTrackerMeta.get_module()) |
453 | | - runtime_name = ( |
454 | | - runtime_base.RuntimeTrackerMeta.get_runtime_name()) |
455 | | - |
456 | | - logger.info("Runtime registered: %s (module: %s)", |
457 | | - runtime_name, runtime_module_name) |
458 | | - |
459 | | - # Extract the package name (e.g., "azure_functions_fastapi" |
460 | | - # from "azure_functions_fastapi.runtime") |
461 | | - # The package is everything before ".runtime" |
462 | | - if '.runtime' in runtime_module_name: |
463 | | - package_name = runtime_module_name.rsplit('.runtime', 1)[0] |
464 | | - else: |
465 | | - # Fallback: use the first part of the module name |
466 | | - package_name = runtime_module_name.split('.')[0] |
467 | | - |
468 | | - logger.debug("Importing runtime package: %s", package_name) |
469 | | - |
470 | | - # Import the top-level runtime package (which exports |
471 | | - # the public API) |
472 | | - runtime_module = importlib.import_module(package_name) |
473 | | - _library_worker = runtime_module |
474 | | - _library_worker_has_cv = hasattr(_library_worker, |
475 | | - 'invocation_id_cv') |
476 | | - |
477 | | - logger.info("Using runtime: %s, version: %s", |
478 | | - runtime_name, |
479 | | - getattr(_library_worker, 'VERSION', 'unknown')) |
| 439 | + for ep in available_runtimes: |
| 440 | + try: |
| 441 | + # Load the entry point (triggers import and |
| 442 | + # metaclass registration) |
| 443 | + ep.load() |
| 444 | + logger.debug(f"Loaded runtime entry point: {ep.name}") |
| 445 | + except Exception as e: |
| 446 | + logger.debug(f"Could not load runtime {ep.name}: {e}") |
| 447 | + continue |
| 448 | + |
| 449 | + # Check if a runtime was registered |
| 450 | + if runtime_base.RuntimeFeatureChecker.runtime_loaded(): |
| 451 | + # Get the registered runtime module |
| 452 | + # (e.g., "azure_functions_fastapi.runtime") |
| 453 | + runtime_module_name = ( |
| 454 | + runtime_base.RuntimeTrackerMeta.get_module()) |
| 455 | + runtime_name = ( |
| 456 | + runtime_base.RuntimeTrackerMeta.get_runtime_name()) |
| 457 | + |
| 458 | + logger.debug("Runtime registered: %s (module: %s)", |
| 459 | + runtime_name, runtime_module_name) |
| 460 | + |
| 461 | + # Extract the package name (e.g., "azure_functions_fastapi" |
| 462 | + # from "azure_functions_fastapi.runtime") |
| 463 | + # The package is everything before ".runtime" |
| 464 | + if '.runtime' in runtime_module_name: |
| 465 | + package_name = runtime_module_name.rsplit('.runtime', 1)[0] |
480 | 466 | else: |
481 | | - # Fallback: No runtime registered via base package |
482 | | - # Use traditional detection (backward compatibility) |
483 | | - logger.debug( |
484 | | - "No runtime registered via base package, using fallback") |
485 | | - v2_scriptfile = os.path.join(directory, get_script_file_name()) |
486 | | - if os.path.exists(v2_scriptfile): |
487 | | - try: |
488 | | - import azure_functions_runtime # NoQA |
489 | | - _library_worker = azure_functions_runtime |
490 | | - _library_worker_has_cv = hasattr( |
491 | | - _library_worker, 'invocation_id_cv') |
492 | | - logger.debug( |
493 | | - "azure_functions_runtime import succeeded: %s", |
494 | | - _library_worker.__file__) |
495 | | - except ImportError: |
496 | | - logger.debug( |
497 | | - "azure_functions_runtime library not found") |
498 | | - else: |
499 | | - try: |
500 | | - import azure_functions_runtime_v1 # NoQA |
501 | | - _library_worker = azure_functions_runtime_v1 |
502 | | - _library_worker_has_cv = hasattr( |
503 | | - _library_worker, 'invocation_id_cv') |
504 | | - logger.debug( |
505 | | - "azure_functions_runtime_v1 import succeeded: %s", |
506 | | - _library_worker.__file__) # type: ignore |
507 | | - except ImportError: |
508 | | - logger.debug( |
509 | | - "azure_functions_runtime_v1 library not found") |
510 | | - |
511 | | - except ImportError as e: |
512 | | - logger.error("Failed to import runtime base package: %s", e) |
513 | | - # Fallback to traditional method |
| 467 | + # Fallback: use the first part of the module name |
| 468 | + package_name = runtime_module_name.split('.')[0] |
| 469 | + |
| 470 | + logger.debug("Importing runtime package: %s", package_name) |
| 471 | + |
| 472 | + # Import the top-level runtime package (which exports |
| 473 | + # the public API) |
| 474 | + runtime_module = importlib.import_module(package_name) |
| 475 | + _library_worker = runtime_module |
| 476 | + _library_worker_has_cv = hasattr(_library_worker, |
| 477 | + 'invocation_id_cv') |
| 478 | + |
| 479 | + else: |
| 480 | + # Fallback: No runtime registered via base package |
| 481 | + # Use traditional detection |
| 482 | + logger.debug( |
| 483 | + "No runtime registered via base package, using fallback") |
514 | 484 | v2_scriptfile = os.path.join(directory, get_script_file_name()) |
515 | 485 | if os.path.exists(v2_scriptfile): |
516 | 486 | try: |
517 | 487 | import azure_functions_runtime # NoQA |
518 | 488 | _library_worker = azure_functions_runtime |
519 | 489 | _library_worker_has_cv = hasattr( |
520 | 490 | _library_worker, 'invocation_id_cv') |
| 491 | + logger.debug( |
| 492 | + "azure_functions_runtime import succeeded: %s", |
| 493 | + _library_worker.__file__) |
521 | 494 | except ImportError: |
522 | | - pass |
| 495 | + logger.debug( |
| 496 | + "azure_functions_runtime library not found") |
523 | 497 | else: |
524 | 498 | try: |
525 | 499 | import azure_functions_runtime_v1 # NoQA |
526 | 500 | _library_worker = azure_functions_runtime_v1 |
527 | 501 | _library_worker_has_cv = hasattr( |
528 | 502 | _library_worker, 'invocation_id_cv') |
| 503 | + logger.debug( |
| 504 | + "azure_functions_runtime_v1 import succeeded: %s", |
| 505 | + _library_worker.__file__) # type: ignore |
529 | 506 | except ImportError: |
530 | | - pass |
| 507 | + logger.debug( |
| 508 | + "azure_functions_runtime_v1 library not found") |
| 509 | + logger.info("Using runtime: %s, version: %s", |
| 510 | + _library_worker, |
| 511 | + getattr(_library_worker, 'VERSION', 'unknown')) |
531 | 512 |
|
532 | 513 | async def _handle__worker_init_request(self, request): |
533 | 514 | logger.info('Received WorkerInitRequest, ' |
|
0 commit comments