Spaces:
Runtime error
Runtime error
Update
Browse files- app.py +21 -73
- constants.py +47 -0
- demo_list.py +63 -30
- restart_scheduler.py +25 -0
- settings.py +5 -0
app.py
CHANGED
|
@@ -2,79 +2,22 @@
|
|
| 2 |
|
| 3 |
from __future__ import annotations
|
| 4 |
|
| 5 |
-
import os
|
| 6 |
-
|
| 7 |
import gradio as gr
|
| 8 |
-
import pandas as pd
|
| 9 |
-
from apscheduler.schedulers.background import BackgroundScheduler
|
| 10 |
-
from huggingface_hub import HfApi
|
| 11 |
|
|
|
|
|
|
|
| 12 |
from demo_list import DemoList
|
|
|
|
|
|
|
| 13 |
|
| 14 |
demo_list = DemoList()
|
| 15 |
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
scheduler = BackgroundScheduler()
|
| 21 |
-
scheduler.add_job(func=lambda: api.restart_space(SPACE_ID),
|
| 22 |
-
trigger='interval',
|
| 23 |
-
seconds=60 * INTERVAL_MIN)
|
| 24 |
scheduler.start()
|
| 25 |
|
| 26 |
-
STATUS_CHOICES = [
|
| 27 |
-
'RUNNING',
|
| 28 |
-
'PAUSED',
|
| 29 |
-
'STOPPED',
|
| 30 |
-
'RUNTIME_ERROR',
|
| 31 |
-
'BUILD_ERROR',
|
| 32 |
-
'BUILDING',
|
| 33 |
-
]
|
| 34 |
-
HARDWARE_CHOICES = [
|
| 35 |
-
'cpu-basic',
|
| 36 |
-
'cpu-upgrade',
|
| 37 |
-
't4-small',
|
| 38 |
-
't4-medium',
|
| 39 |
-
'zero-a10g',
|
| 40 |
-
'a10g-small',
|
| 41 |
-
'a10g-large',
|
| 42 |
-
'a100-large',
|
| 43 |
-
]
|
| 44 |
-
SDK_CHOICES = [
|
| 45 |
-
'gradio',
|
| 46 |
-
'streamlit',
|
| 47 |
-
'docker',
|
| 48 |
-
]
|
| 49 |
-
SLEEP_TIME_CHOICES = list(demo_list.TO_TIME_STR.values())
|
| 50 |
-
SLEEP_TIME_STR_TO_INT = {v: k for k, v in demo_list.TO_TIME_STR.items()}
|
| 51 |
-
OWNER_CHOICES = [WHOAMI, 'other organizations']
|
| 52 |
-
|
| 53 |
-
|
| 54 |
-
def update_df(status: list[str], hardware: list[str], sdk: list[str],
|
| 55 |
-
sleep_time: list[str], owner: list[str],
|
| 56 |
-
multiple_replicas: bool) -> pd.DataFrame:
|
| 57 |
-
df_raw = demo_list.df_raw
|
| 58 |
-
df = demo_list.df
|
| 59 |
-
|
| 60 |
-
if multiple_replicas:
|
| 61 |
-
df = df[df_raw.replicas > 1]
|
| 62 |
-
|
| 63 |
-
df = df[(df_raw.status.isin(status)) & (df_raw.hardware.isin(hardware)) &
|
| 64 |
-
(df_raw.sdk.isin(sdk))]
|
| 65 |
-
|
| 66 |
-
sleep_time_int = [SLEEP_TIME_STR_TO_INT[s] for s in sleep_time]
|
| 67 |
-
df = df[df_raw.sleep_time.isin(sleep_time_int)]
|
| 68 |
-
|
| 69 |
-
if set(owner) == set(OWNER_CHOICES):
|
| 70 |
-
pass
|
| 71 |
-
elif WHOAMI in owner:
|
| 72 |
-
df = df[df_raw.owner == WHOAMI]
|
| 73 |
-
else:
|
| 74 |
-
df = df[df_raw.owner != WHOAMI]
|
| 75 |
-
|
| 76 |
-
return df
|
| 77 |
-
|
| 78 |
|
| 79 |
def update_status_checkboxes(choices: list[str]) -> list[str]:
|
| 80 |
if '(ALL)' in choices:
|
|
@@ -123,20 +66,24 @@ with gr.Blocks(css='style.css') as demo:
|
|
| 123 |
HARDWARE_CHOICES,
|
| 124 |
value=HARDWARE_CHOICES,
|
| 125 |
type='value')
|
| 126 |
-
sdk = gr.CheckboxGroup(label='SDK',
|
| 127 |
-
choices=['(ALL)', '(NONE)'] + SDK_CHOICES,
|
| 128 |
-
value=SDK_CHOICES,
|
| 129 |
-
type='value')
|
| 130 |
sleep_time = gr.CheckboxGroup(label='Sleep time',
|
| 131 |
choices=['(ALL)', '(NONE)'] +
|
| 132 |
SLEEP_TIME_CHOICES,
|
| 133 |
value=SLEEP_TIME_CHOICES,
|
| 134 |
type='value')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 135 |
owner = gr.CheckboxGroup(label='Owner',
|
| 136 |
choices=OWNER_CHOICES,
|
| 137 |
value=OWNER_CHOICES,
|
| 138 |
type='value')
|
| 139 |
-
multiple_replicas = gr.Checkbox(label='Multiple replicas', value=False)
|
| 140 |
apply_button = gr.Button('Apply')
|
| 141 |
df = gr.Dataframe(value=demo_list.df,
|
| 142 |
datatype=demo_list.column_datatype,
|
|
@@ -166,14 +113,15 @@ with gr.Blocks(css='style.css') as demo:
|
|
| 166 |
queue=False,
|
| 167 |
show_progress=False,
|
| 168 |
api_name=False)
|
| 169 |
-
apply_button.click(fn=
|
| 170 |
inputs=[
|
| 171 |
status,
|
| 172 |
hardware,
|
| 173 |
-
sdk,
|
| 174 |
sleep_time,
|
| 175 |
-
owner,
|
| 176 |
multiple_replicas,
|
|
|
|
|
|
|
|
|
|
| 177 |
],
|
| 178 |
outputs=df,
|
| 179 |
api_name=False)
|
|
|
|
| 2 |
|
| 3 |
from __future__ import annotations
|
| 4 |
|
|
|
|
|
|
|
| 5 |
import gradio as gr
|
|
|
|
|
|
|
|
|
|
| 6 |
|
| 7 |
+
from constants import (HARDWARE_CHOICES, OWNER_CHOICES, SDK_CHOICES,
|
| 8 |
+
SLEEP_TIME_CHOICES, STATUS_CHOICES, VISIBILITY_CHOICES)
|
| 9 |
from demo_list import DemoList
|
| 10 |
+
from restart_scheduler import RestartScheduler
|
| 11 |
+
from settings import HF_TOKEN, INTERVAL_MINUTES, SPACE_ID
|
| 12 |
|
| 13 |
demo_list = DemoList()
|
| 14 |
|
| 15 |
+
if SPACE_ID is not None and INTERVAL_MINUTES > 0:
|
| 16 |
+
scheduler = RestartScheduler(space_id=SPACE_ID,
|
| 17 |
+
interval_minutes=INTERVAL_MINUTES,
|
| 18 |
+
hf_token=HF_TOKEN)
|
|
|
|
|
|
|
|
|
|
|
|
|
| 19 |
scheduler.start()
|
| 20 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 21 |
|
| 22 |
def update_status_checkboxes(choices: list[str]) -> list[str]:
|
| 23 |
if '(ALL)' in choices:
|
|
|
|
| 66 |
HARDWARE_CHOICES,
|
| 67 |
value=HARDWARE_CHOICES,
|
| 68 |
type='value')
|
|
|
|
|
|
|
|
|
|
|
|
|
| 69 |
sleep_time = gr.CheckboxGroup(label='Sleep time',
|
| 70 |
choices=['(ALL)', '(NONE)'] +
|
| 71 |
SLEEP_TIME_CHOICES,
|
| 72 |
value=SLEEP_TIME_CHOICES,
|
| 73 |
type='value')
|
| 74 |
+
multiple_replicas = gr.Checkbox(label='Multiple replicas', value=False)
|
| 75 |
+
sdk = gr.CheckboxGroup(label='SDK',
|
| 76 |
+
choices=['(ALL)', '(NONE)'] + SDK_CHOICES,
|
| 77 |
+
value=SDK_CHOICES,
|
| 78 |
+
type='value')
|
| 79 |
+
visibility = gr.CheckboxGroup(label='Visibility',
|
| 80 |
+
choices=VISIBILITY_CHOICES,
|
| 81 |
+
value=VISIBILITY_CHOICES,
|
| 82 |
+
type='value')
|
| 83 |
owner = gr.CheckboxGroup(label='Owner',
|
| 84 |
choices=OWNER_CHOICES,
|
| 85 |
value=OWNER_CHOICES,
|
| 86 |
type='value')
|
|
|
|
| 87 |
apply_button = gr.Button('Apply')
|
| 88 |
df = gr.Dataframe(value=demo_list.df,
|
| 89 |
datatype=demo_list.column_datatype,
|
|
|
|
| 113 |
queue=False,
|
| 114 |
show_progress=False,
|
| 115 |
api_name=False)
|
| 116 |
+
apply_button.click(fn=demo_list.apply_filter,
|
| 117 |
inputs=[
|
| 118 |
status,
|
| 119 |
hardware,
|
|
|
|
| 120 |
sleep_time,
|
|
|
|
| 121 |
multiple_replicas,
|
| 122 |
+
sdk,
|
| 123 |
+
visibility,
|
| 124 |
+
owner,
|
| 125 |
],
|
| 126 |
outputs=df,
|
| 127 |
api_name=False)
|
constants.py
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from huggingface_hub import HfApi
|
| 2 |
+
|
| 3 |
+
STATUS_CHOICES = [
|
| 4 |
+
'RUNNING',
|
| 5 |
+
'PAUSED',
|
| 6 |
+
'STOPPED',
|
| 7 |
+
'RUNTIME_ERROR',
|
| 8 |
+
'BUILD_ERROR',
|
| 9 |
+
'BUILDING',
|
| 10 |
+
'RUNNING_BUILDING',
|
| 11 |
+
'NO_APP_FILE',
|
| 12 |
+
]
|
| 13 |
+
HARDWARE_CHOICES = [
|
| 14 |
+
'cpu-basic',
|
| 15 |
+
'cpu-upgrade',
|
| 16 |
+
't4-small',
|
| 17 |
+
't4-medium',
|
| 18 |
+
'zero-a10g',
|
| 19 |
+
'a10g-small',
|
| 20 |
+
'a10g-large',
|
| 21 |
+
'a100-large',
|
| 22 |
+
]
|
| 23 |
+
SDK_CHOICES = [
|
| 24 |
+
'gradio',
|
| 25 |
+
'streamlit',
|
| 26 |
+
'docker',
|
| 27 |
+
]
|
| 28 |
+
SLEEP_TIME_INT_TO_STR = {
|
| 29 |
+
-1: 'null',
|
| 30 |
+
300: '5 minutes',
|
| 31 |
+
900: '15 minutes',
|
| 32 |
+
1800: '30 minutes',
|
| 33 |
+
3600: '1 hour',
|
| 34 |
+
36000: '10 hours',
|
| 35 |
+
86400: '24 hours',
|
| 36 |
+
172800: '48 hours',
|
| 37 |
+
259200: '72 hours',
|
| 38 |
+
604800: '1 week',
|
| 39 |
+
}
|
| 40 |
+
SLEEP_TIME_CHOICES = list(SLEEP_TIME_INT_TO_STR.values())
|
| 41 |
+
SLEEP_TIME_STR_TO_INT = {v: k for k, v in SLEEP_TIME_INT_TO_STR.items()}
|
| 42 |
+
|
| 43 |
+
VISIBILITY_CHOICES = ['public', 'private']
|
| 44 |
+
|
| 45 |
+
api = HfApi()
|
| 46 |
+
WHOAMI = api.whoami()['name']
|
| 47 |
+
OWNER_CHOICES = [WHOAMI, 'other organizations']
|
demo_list.py
CHANGED
|
@@ -7,6 +7,9 @@ import tqdm.auto
|
|
| 7 |
import yaml
|
| 8 |
from huggingface_hub import HfApi
|
| 9 |
|
|
|
|
|
|
|
|
|
|
| 10 |
repo_dir = pathlib.Path(__file__).parent
|
| 11 |
|
| 12 |
|
|
@@ -29,20 +32,6 @@ class DemoList:
|
|
| 29 |
['replicas', 'markdown'],
|
| 30 |
]
|
| 31 |
|
| 32 |
-
TO_TIME_STR = {
|
| 33 |
-
-1: 'null',
|
| 34 |
-
300: '5 minutes',
|
| 35 |
-
600: '10 minutes',
|
| 36 |
-
900: '15 minutes',
|
| 37 |
-
1800: '30 minutes',
|
| 38 |
-
3600: '1 hour',
|
| 39 |
-
36000: '10 hours',
|
| 40 |
-
86400: '24 hours',
|
| 41 |
-
172800: '48 hours',
|
| 42 |
-
259200: '72 hours',
|
| 43 |
-
604800: '1 week',
|
| 44 |
-
}
|
| 45 |
-
|
| 46 |
def __init__(self):
|
| 47 |
self.api = HfApi()
|
| 48 |
self._raw_data = self.load_data()
|
|
@@ -69,31 +58,39 @@ class DemoList:
|
|
| 69 |
space_id = self.get_space_id(url)
|
| 70 |
space_info = self.api.space_info(repo_id=space_id)
|
| 71 |
card = space_info.cardData
|
| 72 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 73 |
|
| 74 |
for tag in ['arxiv', 'github', 'tags']:
|
| 75 |
if tag not in info:
|
| 76 |
info[tag] = []
|
| 77 |
|
| 78 |
-
|
| 79 |
-
info['owner'] = space_id.split('/')[0]
|
| 80 |
-
info['title'] = card['title']
|
| 81 |
-
info['sdk'] = card['sdk']
|
| 82 |
-
info['sdk_version'] = card.get('sdk_version', '')
|
| 83 |
-
info['likes'] = space_info.likes
|
| 84 |
-
info['last_modified'] = space_info.lastModified
|
| 85 |
-
info['status'] = space_info.runtime['stage']
|
| 86 |
-
|
| 87 |
-
info['suggested_hardware'] = card.get('suggested_hardware', '')
|
| 88 |
info['hardware'] = space_info.runtime['hardware']['current']
|
| 89 |
if info['hardware'] is None:
|
| 90 |
info['hardware'] = space_info.runtime['hardware']['requested']
|
| 91 |
|
| 92 |
-
|
| 93 |
-
|
| 94 |
-
|
| 95 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 96 |
|
|
|
|
| 97 |
resources = space_info.runtime['resources']
|
| 98 |
info['replicas'] = -1 if resources is None else resources[
|
| 99 |
'replicas']
|
|
@@ -175,10 +172,46 @@ class DemoList:
|
|
| 175 |
row.sdk_version,
|
| 176 |
'sleep_time':
|
| 177 |
self.add_div_tag_to_sleep_time(
|
| 178 |
-
|
| 179 |
'replicas':
|
| 180 |
self.add_div_tag_to_replicas(row.replicas),
|
| 181 |
}
|
| 182 |
new_rows.append(new_row)
|
| 183 |
df = pd.DataFrame(new_rows).loc[:, self.column_names]
|
| 184 |
return df
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 7 |
import yaml
|
| 8 |
from huggingface_hub import HfApi
|
| 9 |
|
| 10 |
+
from constants import (OWNER_CHOICES, SLEEP_TIME_INT_TO_STR,
|
| 11 |
+
SLEEP_TIME_STR_TO_INT, WHOAMI)
|
| 12 |
+
|
| 13 |
repo_dir = pathlib.Path(__file__).parent
|
| 14 |
|
| 15 |
|
|
|
|
| 32 |
['replicas', 'markdown'],
|
| 33 |
]
|
| 34 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 35 |
def __init__(self):
|
| 36 |
self.api = HfApi()
|
| 37 |
self._raw_data = self.load_data()
|
|
|
|
| 58 |
space_id = self.get_space_id(url)
|
| 59 |
space_info = self.api.space_info(repo_id=space_id)
|
| 60 |
card = space_info.cardData
|
| 61 |
+
|
| 62 |
+
info: dict = data[url] | {
|
| 63 |
+
'url': url,
|
| 64 |
+
'title': card['title'] if 'title' in card else space_id,
|
| 65 |
+
'owner': space_id.split('/')[0],
|
| 66 |
+
'sdk': card['sdk'],
|
| 67 |
+
'sdk_version': card.get('sdk_version', ''),
|
| 68 |
+
'likes': space_info.likes,
|
| 69 |
+
'private': space_info.private,
|
| 70 |
+
'last_modified': space_info.lastModified,
|
| 71 |
+
'status': space_info.runtime['stage'],
|
| 72 |
+
'suggested_hardware': card.get('suggested_hardware', ''),
|
| 73 |
+
}
|
| 74 |
|
| 75 |
for tag in ['arxiv', 'github', 'tags']:
|
| 76 |
if tag not in info:
|
| 77 |
info[tag] = []
|
| 78 |
|
| 79 |
+
# `current` of paused Spaces is `None`, but `requested` is not
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 80 |
info['hardware'] = space_info.runtime['hardware']['current']
|
| 81 |
if info['hardware'] is None:
|
| 82 |
info['hardware'] = space_info.runtime['hardware']['requested']
|
| 83 |
|
| 84 |
+
# `gcTimeout` is `None` for `cpu-basic` Spaces and Spaces
|
| 85 |
+
# with "Don't sleep" sleep time.
|
| 86 |
+
# We use `-1` to represent it.
|
| 87 |
+
info['sleep_time'] = space_info.runtime['gcTimeout'] or -1
|
| 88 |
+
if info['sleep_time'] not in SLEEP_TIME_INT_TO_STR:
|
| 89 |
+
print(space_id)
|
| 90 |
+
print(f'Unknown sleep time: {info["sleep_time"]}')
|
| 91 |
+
continue
|
| 92 |
|
| 93 |
+
# `resources` of paused Spaces is `None`
|
| 94 |
resources = space_info.runtime['resources']
|
| 95 |
info['replicas'] = -1 if resources is None else resources[
|
| 96 |
'replicas']
|
|
|
|
| 172 |
row.sdk_version,
|
| 173 |
'sleep_time':
|
| 174 |
self.add_div_tag_to_sleep_time(
|
| 175 |
+
SLEEP_TIME_INT_TO_STR[row.sleep_time], row.hardware),
|
| 176 |
'replicas':
|
| 177 |
self.add_div_tag_to_replicas(row.replicas),
|
| 178 |
}
|
| 179 |
new_rows.append(new_row)
|
| 180 |
df = pd.DataFrame(new_rows).loc[:, self.column_names]
|
| 181 |
return df
|
| 182 |
+
|
| 183 |
+
def apply_filter(
|
| 184 |
+
self,
|
| 185 |
+
status: list[str],
|
| 186 |
+
hardware: list[str],
|
| 187 |
+
sleep_time: list[str],
|
| 188 |
+
multiple_replicas: bool,
|
| 189 |
+
sdk: list[str],
|
| 190 |
+
visibility: list[str],
|
| 191 |
+
owner: list[str],
|
| 192 |
+
) -> pd.DataFrame:
|
| 193 |
+
df_raw = self.df_raw
|
| 194 |
+
df = self.df
|
| 195 |
+
|
| 196 |
+
if multiple_replicas:
|
| 197 |
+
df = df[df_raw.replicas > 1]
|
| 198 |
+
|
| 199 |
+
if visibility == ['public']:
|
| 200 |
+
df = df[~df_raw.private]
|
| 201 |
+
elif visibility == ['private']:
|
| 202 |
+
df = df[df_raw.private]
|
| 203 |
+
|
| 204 |
+
df = df[(df_raw.status.isin(status)) & (df_raw.hardware.isin(hardware))
|
| 205 |
+
& (df_raw.sdk.isin(sdk))]
|
| 206 |
+
|
| 207 |
+
sleep_time_int = [SLEEP_TIME_STR_TO_INT[s] for s in sleep_time]
|
| 208 |
+
df = df[df_raw.sleep_time.isin(sleep_time_int)]
|
| 209 |
+
|
| 210 |
+
if set(owner) == set(OWNER_CHOICES):
|
| 211 |
+
pass
|
| 212 |
+
elif WHOAMI in owner:
|
| 213 |
+
df = df[df_raw.owner == WHOAMI]
|
| 214 |
+
else:
|
| 215 |
+
df = df[df_raw.owner != WHOAMI]
|
| 216 |
+
|
| 217 |
+
return df
|
restart_scheduler.py
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from apscheduler.schedulers.background import BackgroundScheduler
|
| 2 |
+
from huggingface_hub import HfApi
|
| 3 |
+
from huggingface_hub.utils import RepositoryNotFoundError
|
| 4 |
+
|
| 5 |
+
|
| 6 |
+
class RestartScheduler:
|
| 7 |
+
def __init__(self, space_id: str, interval_minutes: int,
|
| 8 |
+
hf_token: str | None):
|
| 9 |
+
api = HfApi(token=hf_token)
|
| 10 |
+
if api.get_token_permission() != 'write':
|
| 11 |
+
raise ValueError('The HF token must have write permission.')
|
| 12 |
+
try:
|
| 13 |
+
api.space_info(repo_id=space_id)
|
| 14 |
+
except RepositoryNotFoundError:
|
| 15 |
+
raise ValueError('The Space ID does not exist.')
|
| 16 |
+
if interval_minutes <= 0:
|
| 17 |
+
raise ValueError('The interval must be positive.')
|
| 18 |
+
|
| 19 |
+
self.scheduler = BackgroundScheduler()
|
| 20 |
+
self.scheduler.add_job(func=lambda: api.restart_space(space_id),
|
| 21 |
+
trigger='interval',
|
| 22 |
+
seconds=60 * interval_minutes)
|
| 23 |
+
|
| 24 |
+
def start(self):
|
| 25 |
+
self.scheduler.start()
|
settings.py
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
|
| 3 |
+
HF_TOKEN = os.getenv('HUGGING_FACE_HUB_TOKEN')
|
| 4 |
+
SPACE_ID = os.getenv('SPACE_ID')
|
| 5 |
+
INTERVAL_MINUTES = int(os.getenv('INTERVAL_MINUTES', '30'))
|