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

Enforce quota and hard cap for monthly execution minutes #1284

Merged
merged 44 commits into from
Oct 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
93e50f0
First pass at enforcing execution minutes
tw4l Oct 13, 2023
d203800
Inc execution time in org db throughout crawl
tw4l Oct 13, 2023
9fc1d2e
Cancel crawl if execution mins quota is exceeded while running
tw4l Oct 13, 2023
eccf365
Frontend fixes
tw4l Oct 13, 2023
cb118ee
Implement hard cap for execution minutes
tw4l Oct 13, 2023
7590402
Update execution minutes alert text
tw4l Oct 13, 2023
4bb3839
Check for execution_minutes_hard_cap_reached
tw4l Oct 13, 2023
16ff01b
Move hard cap additional minutes to org owner settings
tw4l Oct 16, 2023
4fe3730
Update field in OrgUpdateExecMinsOverage
tw4l Oct 16, 2023
14e9821
Remove unused user arg
tw4l Oct 16, 2023
3b7855c
Fix setting overage in org owner settings
tw4l Oct 16, 2023
a73568a
Display execution time in crawl detail overview
tw4l Oct 16, 2023
5d86236
Fix setting crawlExecSeconds in crawl
tw4l Oct 16, 2023
a4176c9
Update docstring
tw4l Oct 16, 2023
911bf60
Add backend test for setting org exec time overage
tw4l Oct 16, 2023
1eb5861
Fix and simplify checking quota and hard cap in org
tw4l Oct 17, 2023
05b2969
Cancel crawl immediately when exec minutes hard cap passed
tw4l Oct 17, 2023
2eaed5a
Stop rather than cancel crawl after exec mins hard cap
tw4l Oct 17, 2023
5b590ac
Add org settings billing page docs
tw4l Oct 17, 2023
f4f1ce8
Add nightly tests for quota and hard cap enforcement
tw4l Oct 17, 2023
c18a259
Apply copy changes from code review
tw4l Oct 17, 2023
18314cc
Add inputmode numeric and minutes suffix to hard cap field
tw4l Oct 17, 2023
8f7b5c6
Fix Org Settings Billing page layout
tw4l Oct 17, 2023
e685f9a
Change Billing to Limits
tw4l Oct 19, 2023
32066fc
Update API endpoint to /limits in nightly test
tw4l Oct 19, 2023
15d3769
Change /billing -> /limits in backend tests
tw4l Oct 19, 2023
e0e5890
Merge branch 'main' into issue-1261-execution-time-exceeded
ikreymer Oct 24, 2023
518f739
add null check
ikreymer Oct 24, 2023
d268922
Exec Time Incremental Updates (#1314)
ikreymer Oct 25, 2023
928f913
Issue 1261 execution time exceeded simplify (#1318)
ikreymer Oct 26, 2023
53d4a77
Rename maxCrawlMinutesPerMonth to maxExecMinutesPerMonth
tw4l Oct 26, 2023
f984a02
Fix typing for add_crawl_config
tw4l Oct 26, 2023
e1f3956
Merge branch 'main' into issue-1261-execution-time-exceeded
tw4l Oct 26, 2023
cee0c85
Fix label for maxExecMinutesPerMonth
tw4l Oct 26, 2023
aabe83a
Allow run_now_job to be None
tw4l Oct 26, 2023
7ec514f
Show execution/running minutes meter in dashboard (#1305)
SuaYoo Oct 26, 2023
edd4960
Implement code review changes
tw4l Oct 26, 2023
af76d47
Fix org settings Members tab
tw4l Oct 26, 2023
568db0f
Catch new changed exec_minutes_quota_reached detail
tw4l Oct 26, 2023
fc77738
Disable Run on Save in workflow editor when quotas are hit
tw4l Oct 26, 2023
af3351a
Only go to watch tab if crawl actually started
tw4l Oct 26, 2023
085ed61
Format with Black
tw4l Oct 26, 2023
c5e5363
this -> self
tw4l Oct 26, 2023
4483de9
Remove messages made irrelevant by disabling run on save
tw4l Oct 26, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions backend/btrixcloud/basecrawls.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,9 @@ async def get_crawl(
crawl.config.seeds = None

crawl.storageQuotaReached = await self.orgs.storage_quota_reached(crawl.oid)
crawl.execMinutesQuotaReached = await self.orgs.exec_mins_quota_reached(
crawl.oid
)

return crawl

Expand Down
37 changes: 30 additions & 7 deletions backend/btrixcloud/crawlconfigs.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"""
# pylint: disable=too-many-lines

from typing import List, Union, Optional
from typing import List, Union, Optional, Tuple

import uuid
import asyncio
Expand Down Expand Up @@ -137,7 +137,7 @@ async def add_crawl_config(
config: CrawlConfigIn,
org: Organization,
user: User,
) -> tuple[str, str, bool]:
) -> Tuple[str, Optional[str], bool, bool]:
"""Add new crawl config"""
data = config.dict()
data["oid"] = org.id
Expand Down Expand Up @@ -174,12 +174,17 @@ async def add_crawl_config(
)

run_now = config.runNow
quota_reached = await self.org_ops.storage_quota_reached(org.id)
storage_quota_reached = await self.org_ops.storage_quota_reached(org.id)
exec_mins_quota_reached = await self.org_ops.exec_mins_quota_reached(org.id)

if quota_reached:
if storage_quota_reached:
run_now = False
print(f"Storage quota exceeded for org {org.id}", flush=True)

if exec_mins_quota_reached:
run_now = False
print(f"Execution minutes quota exceeded for org {org.id}", flush=True)

crawl_id = await self.crawl_manager.add_crawl_config(
crawlconfig=crawlconfig,
storage=org.storage,
Expand All @@ -191,7 +196,12 @@ async def add_crawl_config(
if crawl_id and run_now:
await self.add_new_crawl(crawl_id, crawlconfig, user, manual=True)

return result.inserted_id, crawl_id, quota_reached
return (
result.inserted_id,
crawl_id or None,
storage_quota_reached,
exec_mins_quota_reached,
)

async def add_new_crawl(
self, crawl_id: str, crawlconfig: CrawlConfig, user: User, manual: bool
Expand Down Expand Up @@ -336,6 +346,10 @@ async def update_crawl_config(
"updated": True,
"settings_changed": changed,
"metadata_changed": metadata_changed,
"storageQuotaReached": await self.org_ops.storage_quota_reached(org.id),
"execMinutesQuotaReached": await self.org_ops.exec_mins_quota_reached(
org.id
),
}
if run_now:
crawl_id = await self.run_now(cid, org, user)
Expand Down Expand Up @@ -757,6 +771,9 @@ async def run_now(self, cid: uuid.UUID, org: Organization, user: User):
if await self.org_ops.storage_quota_reached(org.id):
raise HTTPException(status_code=403, detail="storage_quota_reached")

if await self.org_ops.exec_mins_quota_reached(org.id):
raise HTTPException(status_code=403, detail="exec_minutes_quota_reached")

try:
crawl_id = await self.crawl_manager.create_crawl_job(
crawlconfig, userid=str(user.id)
Expand Down Expand Up @@ -991,12 +1008,18 @@ async def add_crawl_config(
org: Organization = Depends(org_crawl_dep),
user: User = Depends(user_dep),
):
cid, new_job_name, quota_reached = await ops.add_crawl_config(config, org, user)
(
cid,
new_job_name,
storage_quota_reached,
exec_mins_quota_reached,
) = await ops.add_crawl_config(config, org, user)
return {
"added": True,
"id": str(cid),
"run_now_job": new_job_name,
"storageQuotaReached": quota_reached,
"storageQuotaReached": storage_quota_reached,
"execMinutesQuotaReached": exec_mins_quota_reached,
}

@router.patch("/{cid}", dependencies=[Depends(org_crawl_dep)])
Expand Down
8 changes: 4 additions & 4 deletions backend/btrixcloud/crawls.py
Original file line number Diff line number Diff line change
Expand Up @@ -528,11 +528,11 @@ async def update_running_crawl_stats(self, crawl_id, stats):
query = {"_id": crawl_id, "type": "crawl", "state": "running"}
return await self.crawls.find_one_and_update(query, {"$set": {"stats": stats}})

async def store_exec_time(self, crawl_id, exec_time):
"""set exec time, only if not already set"""
query = {"_id": crawl_id, "type": "crawl", "execTime": {"$in": [0, None]}}
async def inc_crawl_exec_time(self, crawl_id, exec_time):
"""increment exec time"""
return await self.crawls.find_one_and_update(
query, {"$set": {"execTime": exec_time}}
{"_id": crawl_id, "type": "crawl"},
{"$inc": {"crawlExecSeconds": exec_time}},
)

async def get_crawl_state(self, crawl_id):
Expand Down
5 changes: 5 additions & 0 deletions backend/btrixcloud/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -513,6 +513,7 @@ class CrawlOut(BaseMongoModel):
cid_rev: Optional[int]

storageQuotaReached: Optional[bool]
execMinutesQuotaReached: Optional[bool]


# ============================================================================
Expand Down Expand Up @@ -722,6 +723,7 @@ class OrgQuotas(BaseModel):
maxConcurrentCrawls: Optional[int] = 0
maxPagesPerCrawl: Optional[int] = 0
storageQuota: Optional[int] = 0
maxExecMinutesPerMonth: Optional[int] = 0


# ============================================================================
Expand Down Expand Up @@ -755,6 +757,9 @@ class OrgOut(BaseMongoModel):
webhookUrls: Optional[OrgWebhookUrls] = OrgWebhookUrls()
quotas: Optional[OrgQuotas] = OrgQuotas()

storageQuotaReached: Optional[bool]
execMinutesQuotaReached: Optional[bool]


# ============================================================================
class Organization(BaseMongoModel):
Expand Down
Loading
Loading