-
Notifications
You must be signed in to change notification settings - Fork 164
feat(BA-1950): Action Processor to handle various types of targets #5744
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR implements an Action Processor system to handle various types of targets in the AI Backend manager. It introduces a modular architecture with specialized processors for different action types (single entity, scope, and batch operations) along with corresponding validators.
- Refactors the action processing system with type-specific processors and validators
- Adds specialized action classes for single entity, scope, and batch operations
- Moves validation logic to a dedicated validator module structure
Reviewed Changes
Copilot reviewed 16 out of 17 changed files in this pull request and generated 1 comment.
File | Description |
---|---|
src/ai/backend/manager/actions/validators/auth_validator.py | Updates import path for ActionValidator |
src/ai/backend/manager/actions/validator/*.py | Introduces specialized validator classes for different action types |
src/ai/backend/manager/actions/processor/*.py | Implements type-specific action processors with common processing logic |
src/ai/backend/manager/actions/action/*.py | Defines base action classes and specialized action types for different targets |
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
async def _run(self, action: TSingleEntityAction) -> TSingleEntityActionResult: | ||
started_at = datetime.now() | ||
status = OperationStatus.UNKNOWN | ||
description: str = "unknown" | ||
result: Optional[TSingleEntityActionResult] = None | ||
error_code: Optional[ErrorCode] = None | ||
|
||
action_id = uuid.uuid4() | ||
action_trigger_meta = BaseActionTriggerMeta(action_id=action_id, started_at=started_at) | ||
for monitor in self._monitors: | ||
try: | ||
await monitor.prepare(action, action_trigger_meta) | ||
except Exception as e: | ||
log.warning("Error in monitor prepare method: {}", e) | ||
try: | ||
for validator in self._validators: | ||
await validator.validate(action, action_trigger_meta) | ||
result = await self._func(action) | ||
except BackendAIError as e: | ||
log.exception("Action processing error: {}", e) | ||
status = OperationStatus.ERROR | ||
description = str(e) | ||
error_code = e.error_code() | ||
raise | ||
except BaseException as e: | ||
log.exception("Unexpected error during action processing: {}", e) | ||
status = OperationStatus.ERROR | ||
description = str(e) | ||
error_code = ErrorCode.default() | ||
raise | ||
else: | ||
status = OperationStatus.SUCCESS | ||
description = "Success" | ||
return result | ||
finally: | ||
ended_at = datetime.now() | ||
duration = ended_at - started_at | ||
entity_id = action.entity_id() | ||
if entity_id is None and result is not None: | ||
entity_id = result.entity_id() | ||
meta = BaseActionResultMeta( | ||
action_id=action_id, | ||
entity_id=entity_id, | ||
status=status, | ||
description=description, | ||
started_at=started_at, | ||
ended_at=ended_at, | ||
duration=duration, | ||
error_code=error_code, | ||
) | ||
process_result = ProcessResult(meta=meta) | ||
for monitor in reversed(self._monitors): | ||
try: | ||
await monitor.done(action, process_result) | ||
except Exception as e: | ||
log.warning("Error in monitor done method: {}", e) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This entire _run method is duplicated across all three processor classes (single_entity.py, scope.py, batch.py). Consider extracting this common logic into a base class or shared utility function to eliminate code duplication.
Copilot uses AI. Check for mistakes.
class BaseBatchAction(BaseAction): | ||
@override | ||
def entity_id(self) -> Optional[str]: | ||
return None |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the entity_id for backward compatibility?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, it overrides BaseAction
method
bfdd80a
to
2cf1a22
Compare
2cf1a22
to
4db5743
Compare
resolves #5313 (BA-1950)
Checklist: (if applicable)
ai.backend.test
docs
directory