mirror of
https://github.com/clearml/clearml-server
synced 2025-06-16 19:18:06 +00:00
Count own tasks/models for projects
This commit is contained in:
parent
f8b9d9802e
commit
62d5779bd5
@ -183,6 +183,7 @@ class ProjectBLL:
|
|||||||
if new_location != old_location:
|
if new_location != old_location:
|
||||||
raise errors.bad_request.CannotUpdateProjectLocation(name=new_name)
|
raise errors.bad_request.CannotUpdateProjectLocation(name=new_name)
|
||||||
fields["name"] = new_name
|
fields["name"] = new_name
|
||||||
|
fields["basename"] = new_name.split("/")[-1]
|
||||||
|
|
||||||
fields["last_update"] = datetime.utcnow()
|
fields["last_update"] = datetime.utcnow()
|
||||||
updated = project.update(upsert=False, **fields)
|
updated = project.update(upsert=False, **fields)
|
||||||
@ -225,6 +226,7 @@ class ProjectBLL:
|
|||||||
user=user,
|
user=user,
|
||||||
company=company,
|
company=company,
|
||||||
name=name,
|
name=name,
|
||||||
|
basename=name.split("/")[-1],
|
||||||
description=description,
|
description=description,
|
||||||
tags=tags,
|
tags=tags,
|
||||||
system_tags=system_tags,
|
system_tags=system_tags,
|
||||||
@ -328,6 +330,7 @@ class ProjectBLL:
|
|||||||
project_ids: Sequence[str],
|
project_ids: Sequence[str],
|
||||||
specific_state: Optional[EntityVisibility] = None,
|
specific_state: Optional[EntityVisibility] = None,
|
||||||
filter_: Mapping[str, Any] = None,
|
filter_: Mapping[str, Any] = None,
|
||||||
|
users: Sequence[str] = None,
|
||||||
) -> Tuple[Sequence, Sequence]:
|
) -> Tuple[Sequence, Sequence]:
|
||||||
archived = EntityVisibility.archived.value
|
archived = EntityVisibility.archived.value
|
||||||
|
|
||||||
@ -352,7 +355,10 @@ class ProjectBLL:
|
|||||||
# count tasks per project per status
|
# count tasks per project per status
|
||||||
{
|
{
|
||||||
"$match": cls.get_match_conditions(
|
"$match": cls.get_match_conditions(
|
||||||
company=company_id, project_ids=project_ids, filter_=filter_
|
company=company_id,
|
||||||
|
project_ids=project_ids,
|
||||||
|
filter_=filter_,
|
||||||
|
users=users,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
ensure_valid_fields(),
|
ensure_valid_fields(),
|
||||||
@ -469,7 +475,10 @@ class ProjectBLL:
|
|||||||
{
|
{
|
||||||
"$match": {
|
"$match": {
|
||||||
**cls.get_match_conditions(
|
**cls.get_match_conditions(
|
||||||
company=company_id, project_ids=project_ids, filter_=filter_
|
company=company_id,
|
||||||
|
project_ids=project_ids,
|
||||||
|
filter_=filter_,
|
||||||
|
users=users,
|
||||||
),
|
),
|
||||||
**get_state_filter(),
|
**get_state_filter(),
|
||||||
}
|
}
|
||||||
@ -516,13 +525,18 @@ class ProjectBLL:
|
|||||||
include_children: bool = True,
|
include_children: bool = True,
|
||||||
search_hidden: bool = False,
|
search_hidden: bool = False,
|
||||||
filter_: Mapping[str, Any] = None,
|
filter_: Mapping[str, Any] = None,
|
||||||
|
users: Sequence[str] = None,
|
||||||
|
user_active_project_ids: Sequence[str] = None,
|
||||||
) -> Tuple[Dict[str, dict], Dict[str, dict]]:
|
) -> Tuple[Dict[str, dict], Dict[str, dict]]:
|
||||||
if not project_ids:
|
if not project_ids:
|
||||||
return {}, {}
|
return {}, {}
|
||||||
|
|
||||||
child_projects = (
|
child_projects = (
|
||||||
_get_sub_projects(
|
_get_sub_projects(
|
||||||
project_ids, _only=("id", "name"), search_hidden=search_hidden
|
project_ids,
|
||||||
|
_only=("id", "name"),
|
||||||
|
search_hidden=search_hidden,
|
||||||
|
allowed_ids=user_active_project_ids,
|
||||||
)
|
)
|
||||||
if include_children
|
if include_children
|
||||||
else {}
|
else {}
|
||||||
@ -535,6 +549,7 @@ class ProjectBLL:
|
|||||||
project_ids=list(project_ids_with_children),
|
project_ids=list(project_ids_with_children),
|
||||||
specific_state=specific_state,
|
specific_state=specific_state,
|
||||||
filter_=filter_,
|
filter_=filter_,
|
||||||
|
users=users,
|
||||||
)
|
)
|
||||||
|
|
||||||
default_counts = dict.fromkeys(get_options(TaskStatus), 0)
|
default_counts = dict.fromkeys(get_options(TaskStatus), 0)
|
||||||
@ -701,7 +716,7 @@ class ProjectBLL:
|
|||||||
users: Sequence[str],
|
users: Sequence[str],
|
||||||
project_ids: Optional[Sequence[str]] = None,
|
project_ids: Optional[Sequence[str]] = None,
|
||||||
allow_public: bool = True,
|
allow_public: bool = True,
|
||||||
) -> Sequence[str]:
|
) -> Tuple[Sequence[str], Sequence[str]]:
|
||||||
"""
|
"""
|
||||||
Get the projects ids where user created any tasks including all the parents of these projects
|
Get the projects ids where user created any tasks including all the parents of these projects
|
||||||
If project ids are specified then filter the results by these project ids
|
If project ids are specified then filter the results by these project ids
|
||||||
@ -725,13 +740,16 @@ class ProjectBLL:
|
|||||||
|
|
||||||
res = list(res)
|
res = list(res)
|
||||||
if not res:
|
if not res:
|
||||||
return res
|
return res, res
|
||||||
|
|
||||||
ids_with_parents = _ids_with_parents(res)
|
user_active_project_ids = _ids_with_parents(res)
|
||||||
if project_ids:
|
filtered_ids = (
|
||||||
return [pid for pid in ids_with_parents if pid in project_ids]
|
list(set(user_active_project_ids) & set(project_ids))
|
||||||
|
if project_ids
|
||||||
|
else list(user_active_project_ids)
|
||||||
|
)
|
||||||
|
|
||||||
return ids_with_parents
|
return filtered_ids, user_active_project_ids
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_task_parents(
|
def get_task_parents(
|
||||||
@ -800,12 +818,18 @@ class ProjectBLL:
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_match_conditions(
|
def get_match_conditions(
|
||||||
company: str, project_ids: Sequence[str], filter_: Mapping[str, Any]
|
company: str,
|
||||||
|
project_ids: Sequence[str],
|
||||||
|
filter_: Mapping[str, Any],
|
||||||
|
users: Sequence[str],
|
||||||
):
|
):
|
||||||
conditions = {
|
conditions = {
|
||||||
"company": {"$in": [None, "", company]},
|
"company": {"$in": [None, "", company]},
|
||||||
"project": {"$in": project_ids},
|
"project": {"$in": project_ids},
|
||||||
}
|
}
|
||||||
|
if users:
|
||||||
|
conditions["user"] = {"$in": users}
|
||||||
|
|
||||||
if not filter_:
|
if not filter_:
|
||||||
return conditions
|
return conditions
|
||||||
|
|
||||||
@ -828,7 +852,11 @@ class ProjectBLL:
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def calc_own_contents(
|
def calc_own_contents(
|
||||||
cls, company: str, project_ids: Sequence[str], filter_: Mapping[str, Any] = None
|
cls,
|
||||||
|
company: str,
|
||||||
|
project_ids: Sequence[str],
|
||||||
|
filter_: Mapping[str, Any] = None,
|
||||||
|
users: Sequence[str] = None,
|
||||||
) -> Dict[str, dict]:
|
) -> Dict[str, dict]:
|
||||||
"""
|
"""
|
||||||
Returns the amount of task/models per requested project
|
Returns the amount of task/models per requested project
|
||||||
@ -841,7 +869,10 @@ class ProjectBLL:
|
|||||||
pipeline = [
|
pipeline = [
|
||||||
{
|
{
|
||||||
"$match": cls.get_match_conditions(
|
"$match": cls.get_match_conditions(
|
||||||
company=company, project_ids=project_ids, filter_=filter_
|
company=company,
|
||||||
|
project_ids=project_ids,
|
||||||
|
filter_=filter_,
|
||||||
|
users=users,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
{"$project": {"project": 1}},
|
{"$project": {"project": 1}},
|
||||||
|
@ -51,6 +51,7 @@ def _ensure_project(
|
|||||||
created=now,
|
created=now,
|
||||||
last_update=now,
|
last_update=now,
|
||||||
name=name,
|
name=name,
|
||||||
|
basename=name.split("/")[-1],
|
||||||
**(creation_params or dict(description="")),
|
**(creation_params or dict(description="")),
|
||||||
)
|
)
|
||||||
parent = _ensure_project(company, user, location, creation_params=creation_params)
|
parent = _ensure_project(company, user, location, creation_params=creation_params)
|
||||||
@ -104,6 +105,7 @@ def _get_sub_projects(
|
|||||||
project_ids: Sequence[str],
|
project_ids: Sequence[str],
|
||||||
_only: Sequence[str] = ("id", "path"),
|
_only: Sequence[str] = ("id", "path"),
|
||||||
search_hidden=True,
|
search_hidden=True,
|
||||||
|
allowed_ids: Sequence[str] = None,
|
||||||
) -> Mapping[str, Sequence[Project]]:
|
) -> Mapping[str, Sequence[Project]]:
|
||||||
"""
|
"""
|
||||||
Return the list of child projects of all the levels for the parent project ids
|
Return the list of child projects of all the levels for the parent project ids
|
||||||
@ -111,6 +113,9 @@ def _get_sub_projects(
|
|||||||
query = dict(path__in=project_ids)
|
query = dict(path__in=project_ids)
|
||||||
if not search_hidden:
|
if not search_hidden:
|
||||||
query["system_tags__nin"] = [EntityVisibility.hidden.value]
|
query["system_tags__nin"] = [EntityVisibility.hidden.value]
|
||||||
|
if allowed_ids:
|
||||||
|
query["id__in"] = allowed_ids
|
||||||
|
|
||||||
qs = Project.objects(**query)
|
qs = Project.objects(**query)
|
||||||
if _only:
|
if _only:
|
||||||
_only = set(_only) | {"path"}
|
_only = set(_only) | {"path"}
|
||||||
|
@ -12,12 +12,23 @@ events_retrieval {
|
|||||||
# should not exceed the amount of concurrent connections set in the ES driver
|
# should not exceed the amount of concurrent connections set in the ES driver
|
||||||
max_metrics_concurrency: 4
|
max_metrics_concurrency: 4
|
||||||
|
|
||||||
|
# If set then max_metrics_count and max_variants_count are calculated dynamically on user data
|
||||||
|
dynamic_metrics_count: true
|
||||||
|
|
||||||
|
# The percentage from the ES aggs limit (10000) to use for the max_metrics and max_variants calculation
|
||||||
|
dynamic_metrics_count_threshold: 80
|
||||||
|
|
||||||
# the max amount of metrics to aggregate on
|
# the max amount of metrics to aggregate on
|
||||||
max_metrics_count: 100
|
max_metrics_count: 100
|
||||||
|
|
||||||
# the max amount of variants to aggregate on
|
# the max amount of variants to aggregate on
|
||||||
max_variants_count: 100
|
max_variants_count: 100
|
||||||
|
|
||||||
|
debug_images {
|
||||||
|
# Allow to return the debug images for the variants with uninitialized valid iterations border
|
||||||
|
allow_uninitialized_variants: true
|
||||||
|
}
|
||||||
|
|
||||||
max_raw_scalars_size: 200000
|
max_raw_scalars_size: 200000
|
||||||
|
|
||||||
scroll_id_key: "cTN5VEtWEC6QrHvUl0FTx9kNyO0CcCK1p57akxma"
|
scroll_id_key: "cTN5VEtWEC6QrHvUl0FTx9kNyO0CcCK1p57akxma"
|
||||||
|
@ -704,6 +704,45 @@ class GetMixin(PropsMixin):
|
|||||||
v for k, v in cls._field_collation_overrides.items() if field.startswith(k)
|
v for k, v in cls._field_collation_overrides.items() if field.startswith(k)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_count(
|
||||||
|
cls: Union["GetMixin", Document],
|
||||||
|
company,
|
||||||
|
query_dict: dict = None,
|
||||||
|
query_options: QueryParameterOptions = None,
|
||||||
|
query: Q = None,
|
||||||
|
allow_public=False,
|
||||||
|
) -> int:
|
||||||
|
_query = cls._get_combined_query(
|
||||||
|
company=company,
|
||||||
|
query_dict=query_dict,
|
||||||
|
query_options=query_options,
|
||||||
|
query=query,
|
||||||
|
allow_public=allow_public,
|
||||||
|
)
|
||||||
|
return cls.objects(_query).count()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _get_combined_query(
|
||||||
|
cls,
|
||||||
|
company,
|
||||||
|
query_dict: dict = None,
|
||||||
|
query_options: QueryParameterOptions = None,
|
||||||
|
query: Q = None,
|
||||||
|
allow_public=False,
|
||||||
|
) -> Q:
|
||||||
|
if query_dict is not None:
|
||||||
|
q = cls.prepare_query(
|
||||||
|
parameters=query_dict,
|
||||||
|
company=company,
|
||||||
|
parameters_options=query_options,
|
||||||
|
allow_public=allow_public,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
q = cls._prepare_perm_query(company, allow_public=allow_public)
|
||||||
|
|
||||||
|
return (q & query) if query else q
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_many(
|
def get_many(
|
||||||
cls,
|
cls,
|
||||||
@ -749,16 +788,13 @@ class GetMixin(PropsMixin):
|
|||||||
if override_collation:
|
if override_collation:
|
||||||
break
|
break
|
||||||
|
|
||||||
if query_dict is not None:
|
_query = cls._get_combined_query(
|
||||||
q = cls.prepare_query(
|
company=company,
|
||||||
parameters=query_dict,
|
query_dict=query_dict,
|
||||||
company=company,
|
query_options=query_options,
|
||||||
parameters_options=query_options,
|
query=query,
|
||||||
allow_public=allow_public,
|
allow_public=allow_public,
|
||||||
)
|
)
|
||||||
else:
|
|
||||||
q = cls._prepare_perm_query(company, allow_public=allow_public)
|
|
||||||
_query = (q & query) if query else q
|
|
||||||
|
|
||||||
if return_dicts:
|
if return_dicts:
|
||||||
data_getter = partial(
|
data_getter = partial(
|
||||||
|
@ -9,7 +9,7 @@ from apiserver.database.model.base import GetMixin
|
|||||||
class Project(AttributedDocument):
|
class Project(AttributedDocument):
|
||||||
|
|
||||||
get_all_query_options = GetMixin.QueryParameterOptions(
|
get_all_query_options = GetMixin.QueryParameterOptions(
|
||||||
pattern_fields=("name", "description"),
|
pattern_fields=("name", "basename", "description"),
|
||||||
list_fields=("tags", "system_tags", "id", "parent", "path"),
|
list_fields=("tags", "system_tags", "id", "parent", "path"),
|
||||||
range_fields=("last_update",),
|
range_fields=("last_update",),
|
||||||
)
|
)
|
||||||
@ -21,6 +21,7 @@ class Project(AttributedDocument):
|
|||||||
"parent",
|
"parent",
|
||||||
"path",
|
"path",
|
||||||
("company", "name"),
|
("company", "name"),
|
||||||
|
("company", "basename"),
|
||||||
{
|
{
|
||||||
"name": "%s.project.main_text_index" % Database.backend,
|
"name": "%s.project.main_text_index" % Database.backend,
|
||||||
"fields": ["$name", "$id", "$description"],
|
"fields": ["$name", "$id", "$description"],
|
||||||
@ -37,6 +38,7 @@ class Project(AttributedDocument):
|
|||||||
min_length=3,
|
min_length=3,
|
||||||
sparse=True,
|
sparse=True,
|
||||||
)
|
)
|
||||||
|
basename = StrippedStringField(required=True)
|
||||||
description = StringField()
|
description = StringField()
|
||||||
created = DateTimeField(required=True)
|
created = DateTimeField(required=True)
|
||||||
tags = SafeSortedListField(StringField(required=True))
|
tags = SafeSortedListField(StringField(required=True))
|
||||||
|
@ -25,6 +25,10 @@ _definitions {
|
|||||||
description: "Project name"
|
description: "Project name"
|
||||||
type: string
|
type: string
|
||||||
}
|
}
|
||||||
|
basename {
|
||||||
|
description: "Project base name"
|
||||||
|
type: string
|
||||||
|
}
|
||||||
description {
|
description {
|
||||||
description: "Project description"
|
description: "Project description"
|
||||||
type: string
|
type: string
|
||||||
@ -156,6 +160,10 @@ _definitions {
|
|||||||
description: "Project name"
|
description: "Project name"
|
||||||
type: string
|
type: string
|
||||||
}
|
}
|
||||||
|
basename {
|
||||||
|
description: "Project base name"
|
||||||
|
type: string
|
||||||
|
}
|
||||||
description {
|
description {
|
||||||
description: "Project description"
|
description: "Project description"
|
||||||
type: string
|
type: string
|
||||||
@ -214,6 +222,14 @@ _definitions {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
own_tasks {
|
||||||
|
description: "The amount of tasks under this project (without children projects). Returned if 'check_own_contents' flag is set in the request"
|
||||||
|
type: integer
|
||||||
|
}
|
||||||
|
own_models {
|
||||||
|
description: "The amount of models under this project (without children projects). Returned if 'check_own_contents' flag is set in the request"
|
||||||
|
type: integer
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
metric_variant_result {
|
metric_variant_result {
|
||||||
@ -385,6 +401,10 @@ get_all {
|
|||||||
description: "Get only projects whose name matches this pattern (python regular expression syntax)"
|
description: "Get only projects whose name matches this pattern (python regular expression syntax)"
|
||||||
type: string
|
type: string
|
||||||
}
|
}
|
||||||
|
basename {
|
||||||
|
description: "Project base name"
|
||||||
|
type: string
|
||||||
|
}
|
||||||
description {
|
description {
|
||||||
description: "Get only projects whose description matches this pattern (python regular expression syntax)"
|
description: "Get only projects whose description matches this pattern (python regular expression syntax)"
|
||||||
type: string
|
type: string
|
||||||
@ -530,18 +550,6 @@ get_all_ex {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
response {
|
|
||||||
properties {
|
|
||||||
own_tasks {
|
|
||||||
description: "The amount of tasks under this project (without children projects). Returned if 'check_own_contents' flag is set in the request"
|
|
||||||
type: integer
|
|
||||||
}
|
|
||||||
own_models {
|
|
||||||
description: "The amount of models under this project (without children projects). Returned if 'check_own_contents' flag is set in the request"
|
|
||||||
type: integer
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
"2.14": ${get_all_ex."2.13"} {
|
"2.14": ${get_all_ex."2.13"} {
|
||||||
request.properties.search_hidden {
|
request.properties.search_hidden {
|
||||||
|
@ -110,8 +110,9 @@ def get_all_ex(call: APICall, company_id: str, request: ProjectsGetRequest):
|
|||||||
data, shallow_search=request.shallow_search,
|
data, shallow_search=request.shallow_search,
|
||||||
)
|
)
|
||||||
with TimingContext("mongo", "projects_get_all"):
|
with TimingContext("mongo", "projects_get_all"):
|
||||||
|
user_active_project_ids = None
|
||||||
if request.active_users:
|
if request.active_users:
|
||||||
ids = project_bll.get_projects_with_active_user(
|
ids, user_active_project_ids = project_bll.get_projects_with_active_user(
|
||||||
company=company_id,
|
company=company_id,
|
||||||
users=request.active_users,
|
users=request.active_users,
|
||||||
project_ids=requested_ids,
|
project_ids=requested_ids,
|
||||||
@ -139,6 +140,7 @@ def get_all_ex(call: APICall, company_id: str, request: ProjectsGetRequest):
|
|||||||
company=company_id,
|
company=company_id,
|
||||||
project_ids=list(existing_requested_ids),
|
project_ids=list(existing_requested_ids),
|
||||||
filter_=request.include_stats_filter,
|
filter_=request.include_stats_filter,
|
||||||
|
users=request.active_users,
|
||||||
)
|
)
|
||||||
for project in projects:
|
for project in projects:
|
||||||
project.update(**contents.get(project["id"], {}))
|
project.update(**contents.get(project["id"], {}))
|
||||||
@ -156,6 +158,8 @@ def get_all_ex(call: APICall, company_id: str, request: ProjectsGetRequest):
|
|||||||
include_children=request.stats_with_children,
|
include_children=request.stats_with_children,
|
||||||
search_hidden=request.search_hidden,
|
search_hidden=request.search_hidden,
|
||||||
filter_=request.include_stats_filter,
|
filter_=request.include_stats_filter,
|
||||||
|
users=request.active_users,
|
||||||
|
user_active_project_ids=user_active_project_ids,
|
||||||
)
|
)
|
||||||
|
|
||||||
for project in projects:
|
for project in projects:
|
||||||
|
Loading…
Reference in New Issue
Block a user