1- from typing import List , Sequence , TypedDict
1+ from typing import List , Literal , Optional , Sequence , TypedDict , overload
22
3- from typing_extensions import Required , Unpack
3+ from typing_extensions import NotRequired , Required , Unpack
44
5- from .resources import Resource , ResourceParameters , Resources
5+ from .errors import ClientError
6+ from .resources import FinderMethods , Resource , ResourceParameters , Resources
7+
8+ JobTag = Literal [
9+ "unknown" ,
10+ "build_report" ,
11+ "build_site" ,
12+ "build_jupyter" ,
13+ "packrat_restore" ,
14+ "python_restore" ,
15+ "configure_report" ,
16+ "run_app" ,
17+ "run_api" ,
18+ "run_tensorflow" ,
19+ "run_python_api" ,
20+ "run_dash_app" ,
21+ "run_streamlit" ,
22+ "run_bokeh_app" ,
23+ "run_fastapi_app" ,
24+ "run_pyshiny_app" ,
25+ "render_shiny" ,
26+ "run_voila_app" ,
27+ "testing" ,
28+ "git" ,
29+ "val_py_ext_pkg" ,
30+ "val_r_ext_pkg" ,
31+ "val_r_install" ,
32+ ]
633
734
835class Job (Resource ):
9- pass
36+ class _Job (TypedDict ):
37+ # Identifiers
38+ id : Required [str ]
39+ """A unique identifier for the job."""
40+
41+ ppid : Required [Optional [str ]]
42+ """Identifier of the parent process."""
43+
44+ pid : Required [str ]
45+ """Identifier of the process running the job."""
46+
47+ key : Required [str ]
48+ """A unique key to identify this job."""
49+
50+ remote_id : Required [Optional [str ]]
51+ """Identifier for off-host execution configurations."""
52+
53+ app_id : Required [str ]
54+ """Identifier of the parent content associated with the job."""
55+
56+ variant_id : Required [str ]
57+ """Identifier of the variant responsible for the job."""
58+
59+ bundle_id : Required [str ]
60+ """Identifier of the content bundle linked to the job."""
61+
62+ # Timestamps
63+ start_time : Required [str ]
64+ """RFC3339 timestamp indicating when the job started."""
65+
66+ end_time : Required [Optional [str ]]
67+ """RFC3339 timestamp indicating when the job finished."""
68+
69+ last_heartbeat_time : Required [str ]
70+ """RFC3339 timestamp of the last recorded activity for the job."""
71+
72+ queued_time : Required [Optional [str ]]
73+ """RFC3339 timestamp when the job was added to the queue."""
74+
75+ # Status and Exit Information
76+ status : Required [Literal [0 , 1 , 2 ]]
77+ """Current status. Options are 0 (Active), 1 (Finished), and 2 (Finalized)"""
78+
79+ exit_code : Required [Optional [int ]]
80+ """The job's exit code, available after completion."""
1081
82+ # Environment Information
83+ hostname : Required [str ]
84+ """Name of the node processing the job."""
1185
12- class Jobs (Resources , Sequence [Job ]):
86+ cluster : Required [Optional [str ]]
87+ """Location where the job runs, either 'Local' or the cluster name."""
88+
89+ image : Required [Optional [str ]]
90+ """Location of the content in clustered environments."""
91+
92+ run_as : Required [str ]
93+ """UNIX user responsible for executing the job."""
94+
95+ # Queue and Scheduling Information
96+ queue_name : Required [Optional [str ]]
97+ """Name of the queue processing the job, relevant for scheduled reports."""
98+
99+ # Job Metadata
100+ tag : Required [JobTag ]
101+ """A tag categorizing the job type. Options are build_jupyter, build_report, build_site, configure_report, git, packrat_restore, python_restore, render_shiny, run_api, run_app, run_bokeh_app, run_dash_app, run_fastapi_app, run_pyshiny_app, run_python_api, run_streamlit, run_tensorflow, run_voila_app, testing, unknown, val_py_ext_pkg, val_r_ext_pkg, and val_r_install."""
102+
103+ def __init__ (self , / , params , endpoint , ** kwargs : Unpack [_Job ]):
104+ super ().__init__ (params , ** kwargs )
105+ key = kwargs ["key" ]
106+ self ._endpoint = endpoint + key
107+
108+ def destroy (self ) -> None :
109+ """Destroy the job.
110+
111+ Submit a request to kill the job.
112+
113+ Warnings
114+ --------
115+ This operation is irreversible.
116+
117+ Note
118+ ----
119+ This action requires administrator, owner, or collaborator privileges.
120+ """
121+ self .params .session .delete (self ._endpoint )
122+
123+
124+ class Jobs (FinderMethods [Job ], Sequence [Job ], Resources ):
13125 """A collection of jobs."""
14126
15127 def __init__ (self , params , endpoint ):
16- super ().__init__ (params )
17- self ._endpoint = endpoint
128+ super ().__init__ (Job , params , endpoint )
129+ self ._endpoint = endpoint + "jobs"
18130 self ._cache = None
19131
20132 @property
@@ -24,7 +136,7 @@ def _data(self) -> List[Job]:
24136
25137 response = self .params .session .get (self ._endpoint )
26138 results = response .json ()
27- self ._cache = [Job (self .params , ** result ) for result in results ]
139+ self ._cache = [Job (self .params , self . _endpoint , ** result ) for result in results ]
28140 return self ._cache
29141
30142 def __getitem__ (self , index ):
@@ -49,6 +161,143 @@ def index(self, value, start=0, stop=None):
49161 stop = len (self ._data )
50162 return self ._data .index (value , start , stop )
51163
164+ class _FindByRequest (TypedDict , total = False ):
165+ # Identifiers
166+ id : NotRequired [str ]
167+ """A unique identifier for the job."""
168+
169+ ppid : NotRequired [Optional [str ]]
170+ """Identifier of the parent process."""
171+
172+ pid : NotRequired [str ]
173+ """Identifier of the process running the job."""
174+
175+ key : NotRequired [str ]
176+ """A unique key to identify this job."""
177+
178+ remote_id : NotRequired [Optional [str ]]
179+ """Identifier for off-host execution configurations."""
180+
181+ app_id : NotRequired [str ]
182+ """Identifier of the parent content associated with the job."""
183+
184+ variant_id : NotRequired [str ]
185+ """Identifier of the variant responsible for the job."""
186+
187+ bundle_id : NotRequired [str ]
188+ """Identifier of the content bundle linked to the job."""
189+
190+ # Timestamps
191+ start_time : NotRequired [str ]
192+ """RFC3339 timestamp indicating when the job started."""
193+
194+ end_time : NotRequired [Optional [str ]]
195+ """RFC3339 timestamp indicating when the job finished."""
196+
197+ last_heartbeat_time : NotRequired [str ]
198+ """RFC3339 timestamp of the last recorded activity for the job."""
199+
200+ queued_time : NotRequired [Optional [str ]]
201+ """RFC3339 timestamp when the job was added to the queue."""
202+
203+ # Status and Exit Information
204+ status : NotRequired [Literal [0 , 1 , 2 ]]
205+ """Current status. Options are 0 (Active), 1 (Finished), and 2 (Finalized)"""
206+
207+ exit_code : NotRequired [Optional [int ]]
208+ """The job's exit code, available after completion."""
209+
210+ # Environment Information
211+ hostname : NotRequired [str ]
212+ """Name of the node processing the job."""
213+
214+ cluster : NotRequired [Optional [str ]]
215+ """Location where the job runs, either 'Local' or the cluster name."""
216+
217+ image : NotRequired [Optional [str ]]
218+ """Location of the content in clustered environments."""
219+
220+ run_as : NotRequired [str ]
221+ """UNIX user responsible for executing the job."""
222+
223+ # Queue and Scheduling Information
224+ queue_name : NotRequired [Optional [str ]]
225+ """Name of the queue processing the job, relevant for scheduled reports."""
226+
227+ # Job Metadata
228+ tag : NotRequired [JobTag ]
229+ """A tag categorizing the job type. Options are build_jupyter, build_report, build_site, configure_report, git, packrat_restore, python_restore, render_shiny, run_api, run_app, run_bokeh_app, run_dash_app, run_fastapi_app, run_pyshiny_app, run_python_api, run_streamlit, run_tensorflow, run_voila_app, testing, unknown, val_py_ext_pkg, val_r_ext_pkg, and val_r_install."""
230+
231+ @overload
232+ def find_by (self , ** conditions : Unpack [_FindByRequest ]) -> Optional [Job ]:
233+ """Finds the first record matching the specified conditions.
234+
235+ There is no implied ordering so if order matters, you should specify it yourself.
236+
237+ Parameters
238+ ----------
239+ id : str, not required
240+ A unique identifier for the job.
241+ ppid : Optional[str], not required
242+ Identifier of the parent process.
243+ pid : str, not required
244+ Identifier of the process running the job.
245+ key : str, not required
246+ A unique key to identify this job.
247+ remote_id : Optional[str], not required
248+ Identifier for off-host execution configurations.
249+ app_id : str, not required
250+ Identifier of the parent content associated with the job.
251+ variant_id : str, not required
252+ Identifier of the variant responsible for the job.
253+ bundle_id : str, not required
254+ Identifier of the content bundle linked to the job.
255+ start_time : str, not required
256+ RFC3339 timestamp indicating when the job started.
257+ end_time : Optional[str], not required
258+ RFC3339 timestamp indicating when the job finished.
259+ last_heartbeat_time : str, not required
260+ RFC3339 timestamp of the last recorded activity for the job.
261+ queued_time : Optional[str], not required
262+ RFC3339 timestamp when the job was added to the queue.
263+ status : int, not required
264+ Current status. Options are 0 (Active), 1 (Finished), and 2 (Finalized)
265+ exit_code : Optional[int], not required
266+ The job's exit code, available after completion.
267+ hostname : str, not required
268+ Name of the node processing the job.
269+ cluster : Optional[str], not required
270+ Location where the job runs, either 'Local' or the cluster name.
271+ image : Optional[str], not required
272+ Location of the content in clustered environments.
273+ run_as : str, not required
274+ UNIX user responsible for executing the job.
275+ queue_name : Optional[str], not required
276+ Name of the queue processing the job, relevant for scheduled reports.
277+ tag : JobTag, not required
278+ A tag categorizing the job type. Options are build_jupyter, build_report, build_site, configure_report, git, packrat_restore, python_restore, render_shiny, run_api, run_app, run_bokeh_app, run_dash_app, run_fastapi_app, run_pyshiny_app, run_python_api, run_streamlit, run_tensorflow, run_voila_app, testing, unknown, val_py_ext_pkg, val_r_ext_pkg, and val_r_install.
279+
280+ Returns
281+ -------
282+ Optional[Job]
283+ """
284+ ...
285+
286+ @overload
287+ def find_by (self , ** conditions ): ...
288+
289+ def find_by (self , ** conditions ):
290+ if "key" in conditions and self ._cache is None :
291+ key = conditions ["key" ]
292+ try :
293+ return self .find (key )
294+ except ClientError as e :
295+ if e .http_status == 404 :
296+ return None
297+ raise e
298+
299+ return super ().find_by (** conditions )
300+
52301 def reload (self ) -> "Jobs" :
53302 """Unload the cached jobs.
54303
@@ -69,5 +318,5 @@ class HasGuid(TypedDict):
69318 def __init__ (self , params : ResourceParameters , ** kwargs : Unpack [HasGuid ]):
70319 super ().__init__ (params , ** kwargs )
71320 uid = kwargs ["guid" ]
72- endpoint = self .params .url + f"v1/content/{ uid } /jobs "
321+ endpoint = self .params .url + f"v1/content/{ uid } "
73322 self .jobs = Jobs (self .params , endpoint )
0 commit comments