Skip to content
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

Refactor way of working with RQ meta #9082

Open
wants to merge 29 commits into
base: develop
Choose a base branch
from

Conversation

Marishka17
Copy link
Contributor

@Marishka17 Marishka17 commented Feb 10, 2025

Motivation and context

This PR changes the way we work with RQ meta. The previous implementation tried to standardize the fields saved in the meta and how to access them, however, we had to remember the structure of nested objects. This approach explicitly defines the structure of the meta being used.
Extracted from #9075
Partially depends on #9077

How has this been tested?

Checklist

  • I submit my changes into the develop branch
  • I have created a changelog fragment
  • I have updated the documentation accordingly
  • I have added tests to cover my changes
  • I have linked related issues (see GitHub docs)

License

  • I submit my code changes under the same MIT License that covers the project.
    Feel free to contact the maintainers if that's a concern.

@cvat-ai cvat-ai deleted a comment from github-actions bot Feb 10, 2025
Copy link
Contributor

github-actions bot commented Feb 10, 2025

❌ Some checks failed
📄 See logs here

Copy link
Contributor

github-actions bot commented Feb 10, 2025

❌ Some checks failed
📄 See logs here

@Marishka17 Marishka17 changed the title [WIP] Refactor way of working with RQ meta [do not merge] Refactor way of working with RQ meta Feb 10, 2025
@codecov-commenter
Copy link

codecov-commenter commented Feb 12, 2025

Codecov Report

Attention: Patch coverage is 79.05237% with 84 lines in your changes missing coverage. Please review.

Project coverage is 73.89%. Comparing base (558a861) to head (a0b7a74).
Report is 2 commits behind head on develop.

Additional details and impacted files
@@             Coverage Diff             @@
##           develop    #9082      +/-   ##
===========================================
+ Coverage    73.83%   73.89%   +0.06%     
===========================================
  Files          431      432       +1     
  Lines        44807    44984     +177     
  Branches      3892     3892              
===========================================
+ Hits         33084    33243     +159     
- Misses       11723    11741      +18     
Components Coverage Δ
cvat-ui 77.52% <ø> (-0.02%) ⬇️
cvat-server 70.94% <77.64%> (+0.14%) ⬆️

@Marishka17 Marishka17 changed the title [do not merge] Refactor way of working with RQ meta Refactor way of working with RQ meta Feb 12, 2025
@Marishka17 Marishka17 force-pushed the mk/refactor_working_with_rq_meta branch from 3348a62 to 7ea0523 Compare February 14, 2025 16:02
@Marishka17 Marishka17 requested a review from nmanovic as a code owner February 17, 2025 10:53
@Marishka17 Marishka17 changed the title Refactor way of working with RQ meta [WIP] Refactor way of working with RQ meta Feb 19, 2025
@cvat-ai cvat-ai deleted a comment from github-actions bot Feb 21, 2025
@Marishka17 Marishka17 force-pushed the mk/refactor_working_with_rq_meta branch from b99d1b2 to 9ce85ac Compare February 21, 2025 11:31
@Marishka17 Marishka17 changed the title [WIP] Refactor way of working with RQ meta Refactor way of working with RQ meta Feb 21, 2025
pass


class UserRQMetaAttribute(ImmutableRQMetaAttribute):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think you're actually getting anything from the parent class here. This class could be reduced to:

class UserRQMetaAttribute:
    def __get__(self, instance: WithMeta, objtype: type[WithMeta] | None = None):
        return UserMeta(instance.meta[RQJobMetaField.USER])

(In fact, I think it could even be replaced with a property in BaseRQMeta.)

pass


class MutableRQMetaAttribute(_GettableRQMetaAttribute, _SettableRQMetaAttribute):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't seem like 5 classes are needed here. They could be combined into two - ImmutableRQMetaAttribute (merged _AbstractRQMetaAttribute and _GettableRQMetaAttribute), and MutableRQMetaAttribute (same as _SettableRQMetaAttribute, but inheriting from ImmutableRQMetaAttribute).

RQJobMetaField.UserField.EMAIL, validator=lambda x: isinstance(x, str)
)

def __init__(self, meta: dict[RQJobMetaField.UserField, Any]) -> None:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This type annotation is incorrect, because e.g. UserField.ID is not an instance of UserField.

Comment on lines +136 to +137
def to_dict(self):
return self.meta
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aren't these redundant?

) -> None:
assert validator is None or callable(validator), "validator must be callable"
self._key = key
self._validator = validator
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The validator parameter ought to be moved to _SettableRQMetaAttribute, since it doesn't do anything in an immutable attribute.

if value is None and not self._optional:
raise ValueError(f"{self._key} is required")
if value is not None and self._validator and not self._validator(value):
raise ValueError("Wrong type")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO, if the validator can only signal that the type is wrong, then you might as well replace the validator parameter with something like expected_type.


@classmethod
def for_job(cls, job: RQJob):
return cls(job=job)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return cls(job=job)
return cls(job=job, meta=job.meta)

This would simplify the rest of the class: no need for the if in def meta, no need for the assert in __init__.

{
RQJobMetaField.UserField.ID: user.id,
RQJobMetaField.UserField.USERNAME: user.username,
RQJobMetaField.UserField.EMAIL: getattr(user, "email", ""),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How could email be a missing attribute? Isn't it part of the User model?

RQJobMetaField.REQUEST: RequestMeta(
{
RQJobMetaField.RequestField.UUID: request.uuid,
RQJobMetaField.RequestField.TIMESTAMP: timezone.localtime(),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why local time?


user = request.user

return cls.for_meta(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't the class redundant here? You're creating a dictionary, wrapping it, then immediately unwrapping it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants