flamepy 0.3.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- flamepy/__init__.py +82 -0
- flamepy/client.py +433 -0
- flamepy/frontend_pb2.py +68 -0
- flamepy/frontend_pb2_grpc.py +709 -0
- flamepy/service.py +225 -0
- flamepy/shim_pb2.py +46 -0
- flamepy/shim_pb2_grpc.py +184 -0
- flamepy/test_flame.py +195 -0
- flamepy/types.py +159 -0
- flamepy/types_pb2.py +95 -0
- flamepy/types_pb2_grpc.py +24 -0
- flamepy-0.3.0.dist-info/METADATA +177 -0
- flamepy-0.3.0.dist-info/RECORD +16 -0
- flamepy-0.3.0.dist-info/WHEEL +5 -0
- flamepy-0.3.0.dist-info/licenses/LICENSE +201 -0
- flamepy-0.3.0.dist-info/top_level.txt +1 -0
flamepy/__init__.py
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
|
|
2
|
+
from .types import (
|
|
3
|
+
# Type aliases
|
|
4
|
+
TaskID,
|
|
5
|
+
SessionID,
|
|
6
|
+
ApplicationID,
|
|
7
|
+
Message,
|
|
8
|
+
TaskInput,
|
|
9
|
+
TaskOutput,
|
|
10
|
+
CommonData,
|
|
11
|
+
|
|
12
|
+
# Enums
|
|
13
|
+
SessionState,
|
|
14
|
+
TaskState,
|
|
15
|
+
Shim,
|
|
16
|
+
|
|
17
|
+
FlameErrorCode,
|
|
18
|
+
|
|
19
|
+
# Classes
|
|
20
|
+
FlameError,
|
|
21
|
+
SessionAttributes,
|
|
22
|
+
ApplicationAttributes,
|
|
23
|
+
Task,
|
|
24
|
+
Application,
|
|
25
|
+
FlameContext,
|
|
26
|
+
TaskInformer,
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
from .client import Connection, Session, TaskWatcher, connect, create_session
|
|
30
|
+
from .service import (
|
|
31
|
+
FlameService,
|
|
32
|
+
ApplicationContext, SessionContext, TaskContext, TaskOutput,
|
|
33
|
+
run
|
|
34
|
+
)
|
|
35
|
+
__version__ = "0.1.0"
|
|
36
|
+
|
|
37
|
+
__all__ = [
|
|
38
|
+
# Type aliases
|
|
39
|
+
"TaskID",
|
|
40
|
+
"SessionID",
|
|
41
|
+
"ApplicationID",
|
|
42
|
+
"Message",
|
|
43
|
+
"TaskInput",
|
|
44
|
+
"TaskOutput",
|
|
45
|
+
"CommonData",
|
|
46
|
+
|
|
47
|
+
# Enums
|
|
48
|
+
"SessionState",
|
|
49
|
+
"TaskState",
|
|
50
|
+
"ApplicationState",
|
|
51
|
+
"Shim",
|
|
52
|
+
"FlameErrorCode",
|
|
53
|
+
|
|
54
|
+
# Service classes
|
|
55
|
+
"FlameService",
|
|
56
|
+
"ApplicationContext",
|
|
57
|
+
"SessionContext",
|
|
58
|
+
"TaskContext",
|
|
59
|
+
"TaskOutput",
|
|
60
|
+
"run",
|
|
61
|
+
|
|
62
|
+
# Classes
|
|
63
|
+
"FlameError",
|
|
64
|
+
"SessionAttributes",
|
|
65
|
+
"ApplicationAttributes",
|
|
66
|
+
"Session",
|
|
67
|
+
"Task",
|
|
68
|
+
"Application",
|
|
69
|
+
"FlameContext",
|
|
70
|
+
"TaskInformer",
|
|
71
|
+
|
|
72
|
+
# Client classes
|
|
73
|
+
"Connection",
|
|
74
|
+
"connect",
|
|
75
|
+
"create_session",
|
|
76
|
+
"TaskWatcher",
|
|
77
|
+
"Session",
|
|
78
|
+
"Task",
|
|
79
|
+
"TaskInput",
|
|
80
|
+
"TaskOutput",
|
|
81
|
+
"CommonData",
|
|
82
|
+
]
|
flamepy/client.py
ADDED
|
@@ -0,0 +1,433 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Copyright 2025 The Flame Authors.
|
|
3
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
you may not use this file except in compliance with the License.
|
|
5
|
+
You may obtain a copy of the License at
|
|
6
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
7
|
+
Unless required by applicable law or agreed to in writing, software
|
|
8
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
9
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
10
|
+
See the License for the specific language governing permissions and
|
|
11
|
+
limitations under the License.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
import asyncio
|
|
15
|
+
import threading
|
|
16
|
+
from typing import Optional, List, Dict, Any, Union
|
|
17
|
+
from urllib.parse import urlparse
|
|
18
|
+
import grpc
|
|
19
|
+
import grpc.aio
|
|
20
|
+
import os
|
|
21
|
+
|
|
22
|
+
from datetime import datetime
|
|
23
|
+
from .types import (
|
|
24
|
+
Task, Application, SessionAttributes, ApplicationAttributes,
|
|
25
|
+
SessionID, TaskID, ApplicationID, TaskInput, TaskOutput, CommonData,
|
|
26
|
+
SessionState, TaskState, ApplicationState, Shim, FlameError, FlameErrorCode,
|
|
27
|
+
TaskInformer
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
from .types_pb2 import ApplicationSpec, SessionSpec, TaskSpec
|
|
31
|
+
from .frontend_pb2 import RegisterApplicationRequest, UnregisterApplicationRequest, ListApplicationRequest, CreateSessionRequest, ListSessionRequest, GetSessionRequest, CloseSessionRequest, CreateTaskRequest, WatchTaskRequest, GetTaskRequest
|
|
32
|
+
from .frontend_pb2_grpc import FrontendStub
|
|
33
|
+
|
|
34
|
+
async def connect(addr: str) -> "Connection":
|
|
35
|
+
"""Connect to the Flame service."""
|
|
36
|
+
return await Connection.connect(addr)
|
|
37
|
+
|
|
38
|
+
async def create_session(application: str, common_data: Dict[str, Any] = None, slots: int = 1) -> "Session":
|
|
39
|
+
conn = await ConnectionInstance().instance()
|
|
40
|
+
session = await conn.create_session(SessionAttributes(application=application, common_data=common_data, slots=slots))
|
|
41
|
+
return session
|
|
42
|
+
|
|
43
|
+
class ConnectionInstance:
|
|
44
|
+
"""Connection instance."""
|
|
45
|
+
_connection = None
|
|
46
|
+
_lock = threading.Lock()
|
|
47
|
+
|
|
48
|
+
async def instance(self) -> "Connection":
|
|
49
|
+
"""Get the connection instance."""
|
|
50
|
+
with self._lock:
|
|
51
|
+
if not self._connection:
|
|
52
|
+
self._connection = await connect(os.getenv("FLAME_ENDPOINT", "http://127.0.0.1:8080"))
|
|
53
|
+
return self._connection
|
|
54
|
+
|
|
55
|
+
class Connection:
|
|
56
|
+
"""Connection to the Flame service."""
|
|
57
|
+
|
|
58
|
+
def __init__(self, addr: str, channel: grpc.aio.Channel, frontend: FrontendStub):
|
|
59
|
+
self.addr = addr
|
|
60
|
+
self._channel = channel
|
|
61
|
+
self._frontend = frontend
|
|
62
|
+
|
|
63
|
+
@classmethod
|
|
64
|
+
async def connect(cls, addr: str) -> "Connection":
|
|
65
|
+
"""Establish a connection to the Flame service."""
|
|
66
|
+
if not addr:
|
|
67
|
+
raise FlameError(
|
|
68
|
+
FlameErrorCode.INVALID_CONFIG,
|
|
69
|
+
"address cannot be empty"
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
try:
|
|
73
|
+
parsed_addr = urlparse(addr)
|
|
74
|
+
host = parsed_addr.hostname or parsed_addr.path
|
|
75
|
+
port = parsed_addr.port or 8080
|
|
76
|
+
|
|
77
|
+
# Create insecure channel
|
|
78
|
+
channel = grpc.aio.insecure_channel(f"{host}:{port}")
|
|
79
|
+
|
|
80
|
+
# Wait for channel to be ready
|
|
81
|
+
await channel.channel_ready()
|
|
82
|
+
|
|
83
|
+
# Create frontend stub
|
|
84
|
+
frontend = FrontendStub(channel)
|
|
85
|
+
|
|
86
|
+
return cls(addr, channel, frontend)
|
|
87
|
+
|
|
88
|
+
except Exception as e:
|
|
89
|
+
raise FlameError(
|
|
90
|
+
FlameErrorCode.INVALID_CONFIG,
|
|
91
|
+
f"failed to connect to {addr}: {str(e)}"
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
async def close(self) -> None:
|
|
95
|
+
"""Close the connection."""
|
|
96
|
+
await self._channel.close()
|
|
97
|
+
|
|
98
|
+
async def register_application(
|
|
99
|
+
self,
|
|
100
|
+
name: str,
|
|
101
|
+
app_attrs: Union[ApplicationAttributes, Dict[str, Any]]
|
|
102
|
+
) -> None:
|
|
103
|
+
"""Register a new application."""
|
|
104
|
+
if isinstance(app_attrs, dict):
|
|
105
|
+
app_attrs = ApplicationAttributes(**app_attrs)
|
|
106
|
+
|
|
107
|
+
app_spec = ApplicationSpec(
|
|
108
|
+
shim=app_attrs.shim,
|
|
109
|
+
url=app_attrs.url,
|
|
110
|
+
command=app_attrs.command,
|
|
111
|
+
arguments=app_attrs.arguments or [],
|
|
112
|
+
environments=app_attrs.environments or [],
|
|
113
|
+
working_directory=app_attrs.working_directory
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
request = RegisterApplicationRequest(
|
|
117
|
+
name=name,
|
|
118
|
+
application=app_spec
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
try:
|
|
122
|
+
await self._frontend.RegisterApplication(request)
|
|
123
|
+
except grpc.RpcError as e:
|
|
124
|
+
raise FlameError(
|
|
125
|
+
FlameErrorCode.INTERNAL,
|
|
126
|
+
f"failed to register application: {e.details()}"
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
async def unregister_application(self, name: str) -> None:
|
|
130
|
+
"""Unregister an application."""
|
|
131
|
+
request = UnregisterApplicationRequest(name=name)
|
|
132
|
+
|
|
133
|
+
try:
|
|
134
|
+
await self._frontend.UnregisterApplication(request)
|
|
135
|
+
except grpc.RpcError as e:
|
|
136
|
+
raise FlameError(
|
|
137
|
+
FlameErrorCode.INTERNAL,
|
|
138
|
+
f"failed to unregister application: {e.details()}"
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
async def list_applications(self) -> List[Application]:
|
|
142
|
+
"""List all applications."""
|
|
143
|
+
request = ListApplicationRequest()
|
|
144
|
+
|
|
145
|
+
try:
|
|
146
|
+
response = await self._frontend.ListApplication(request)
|
|
147
|
+
|
|
148
|
+
applications = []
|
|
149
|
+
for app in response.applications:
|
|
150
|
+
applications.append(Application(
|
|
151
|
+
id=app.metadata.id,
|
|
152
|
+
name=app.metadata.name,
|
|
153
|
+
shim=Shim(app.spec.shim),
|
|
154
|
+
state=ApplicationState(app.status.state),
|
|
155
|
+
creation_time=datetime.fromtimestamp(app.status.creation_time),
|
|
156
|
+
url=app.spec.url,
|
|
157
|
+
command=app.spec.command,
|
|
158
|
+
arguments=list(app.spec.arguments),
|
|
159
|
+
environments=list(app.spec.environments),
|
|
160
|
+
working_directory=app.spec.working_directory
|
|
161
|
+
))
|
|
162
|
+
|
|
163
|
+
return applications
|
|
164
|
+
|
|
165
|
+
except grpc.RpcError as e:
|
|
166
|
+
raise FlameError(
|
|
167
|
+
FlameErrorCode.INTERNAL,
|
|
168
|
+
f"failed to list applications: {e.details()}"
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
async def create_session(self, attrs: SessionAttributes) -> "Session":
|
|
172
|
+
"""Create a new session."""
|
|
173
|
+
session_spec = SessionSpec(
|
|
174
|
+
application=attrs.application,
|
|
175
|
+
slots=attrs.slots,
|
|
176
|
+
common_data=attrs.common_data
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
request = CreateSessionRequest(session=session_spec)
|
|
180
|
+
|
|
181
|
+
try:
|
|
182
|
+
response = await self._frontend.CreateSession(request)
|
|
183
|
+
|
|
184
|
+
session = Session(
|
|
185
|
+
connection=self,
|
|
186
|
+
id=response.metadata.id,
|
|
187
|
+
application=response.spec.application,
|
|
188
|
+
slots=response.spec.slots,
|
|
189
|
+
state=SessionState(response.status.state),
|
|
190
|
+
creation_time=datetime.fromtimestamp(response.status.creation_time),
|
|
191
|
+
pending=response.status.pending,
|
|
192
|
+
running=response.status.running,
|
|
193
|
+
succeed=response.status.succeed,
|
|
194
|
+
failed=response.status.failed,
|
|
195
|
+
completion_time=datetime.fromtimestamp(response.status.completion_time) if response.status.HasField('completion_time') else None
|
|
196
|
+
)
|
|
197
|
+
return session
|
|
198
|
+
except grpc.RpcError as e:
|
|
199
|
+
raise FlameError(
|
|
200
|
+
FlameErrorCode.INTERNAL,
|
|
201
|
+
f"failed to create session: {e.details()}"
|
|
202
|
+
)
|
|
203
|
+
|
|
204
|
+
async def list_sessions(self) -> List["Session"]:
|
|
205
|
+
"""List all sessions."""
|
|
206
|
+
request = ListSessionRequest()
|
|
207
|
+
|
|
208
|
+
try:
|
|
209
|
+
response = await self._frontend.ListSession(request)
|
|
210
|
+
|
|
211
|
+
sessions = []
|
|
212
|
+
for session in response.sessions:
|
|
213
|
+
sessions.append(Session(
|
|
214
|
+
connection=self,
|
|
215
|
+
id=session.metadata.id,
|
|
216
|
+
application=session.spec.application,
|
|
217
|
+
slots=session.spec.slots,
|
|
218
|
+
state=SessionState(session.status.state),
|
|
219
|
+
creation_time=datetime.fromtimestamp(session.status.creation_time),
|
|
220
|
+
pending=session.status.pending,
|
|
221
|
+
running=session.status.running,
|
|
222
|
+
succeed=session.status.succeed,
|
|
223
|
+
failed=session.status.failed,
|
|
224
|
+
completion_time=datetime.fromtimestamp(session.status.completion_time) if session.status.HasField('completion_time') else None
|
|
225
|
+
))
|
|
226
|
+
|
|
227
|
+
return sessions
|
|
228
|
+
|
|
229
|
+
except grpc.RpcError as e:
|
|
230
|
+
raise FlameError(
|
|
231
|
+
FlameErrorCode.INTERNAL,
|
|
232
|
+
f"failed to list sessions: {e.details()}"
|
|
233
|
+
)
|
|
234
|
+
|
|
235
|
+
async def get_session(self, session_id: SessionID) -> "Session":
|
|
236
|
+
"""Get a session by ID."""
|
|
237
|
+
request = GetSessionRequest(session_id=session_id)
|
|
238
|
+
|
|
239
|
+
try:
|
|
240
|
+
response = await self._frontend.GetSession(request)
|
|
241
|
+
|
|
242
|
+
return Session(
|
|
243
|
+
connection=self,
|
|
244
|
+
id=response.metadata.id,
|
|
245
|
+
application=response.spec.application,
|
|
246
|
+
slots=response.spec.slots,
|
|
247
|
+
state=SessionState(response.status.state),
|
|
248
|
+
creation_time=datetime.fromtimestamp(response.status.creation_time),
|
|
249
|
+
pending=response.status.pending,
|
|
250
|
+
running=response.status.running,
|
|
251
|
+
succeed=response.status.succeed,
|
|
252
|
+
failed=response.status.failed,
|
|
253
|
+
completion_time=datetime.fromtimestamp(response.status.completion_time) if response.status.HasField('completion_time') else None
|
|
254
|
+
)
|
|
255
|
+
|
|
256
|
+
except grpc.RpcError as e:
|
|
257
|
+
raise FlameError(
|
|
258
|
+
FlameErrorCode.INTERNAL,
|
|
259
|
+
f"failed to get session: {e.details()}"
|
|
260
|
+
)
|
|
261
|
+
|
|
262
|
+
async def close_session(self, session_id: SessionID) -> "Session":
|
|
263
|
+
"""Close a session."""
|
|
264
|
+
request = CloseSessionRequest(session_id=session_id)
|
|
265
|
+
|
|
266
|
+
try:
|
|
267
|
+
response = await self._frontend.CloseSession(request)
|
|
268
|
+
|
|
269
|
+
return Session(
|
|
270
|
+
connection=self,
|
|
271
|
+
id=response.metadata.id,
|
|
272
|
+
application=response.spec.application,
|
|
273
|
+
slots=response.spec.slots,
|
|
274
|
+
state=SessionState(response.status.state),
|
|
275
|
+
creation_time=datetime.fromtimestamp(response.status.creation_time),
|
|
276
|
+
pending=response.status.pending,
|
|
277
|
+
running=response.status.running,
|
|
278
|
+
succeed=response.status.succeed,
|
|
279
|
+
failed=response.status.failed,
|
|
280
|
+
completion_time=datetime.fromtimestamp(response.status.completion_time) if response.status.HasField('completion_time') else None
|
|
281
|
+
)
|
|
282
|
+
|
|
283
|
+
except grpc.RpcError as e:
|
|
284
|
+
raise FlameError(
|
|
285
|
+
FlameErrorCode.INTERNAL,
|
|
286
|
+
f"failed to close session: {e.details()}"
|
|
287
|
+
)
|
|
288
|
+
|
|
289
|
+
class Session:
|
|
290
|
+
connection: Connection
|
|
291
|
+
|
|
292
|
+
"""Represents a computing session."""
|
|
293
|
+
id: SessionID
|
|
294
|
+
application: str
|
|
295
|
+
slots: int
|
|
296
|
+
state: SessionState
|
|
297
|
+
creation_time: datetime
|
|
298
|
+
pending: int = 0
|
|
299
|
+
running: int = 0
|
|
300
|
+
succeed: int = 0
|
|
301
|
+
failed: int = 0
|
|
302
|
+
completion_time: Optional[datetime] = None
|
|
303
|
+
|
|
304
|
+
"""Client for session-specific operations."""
|
|
305
|
+
|
|
306
|
+
def __init__(self, connection: Connection, id: SessionID, application: str, slots: int, state: SessionState, creation_time: datetime, pending: int, running: int, succeed: int, failed: int, completion_time: Optional[datetime]):
|
|
307
|
+
self.connection = connection
|
|
308
|
+
self.id = id
|
|
309
|
+
self.application = application
|
|
310
|
+
self.slots = slots
|
|
311
|
+
self.state = state
|
|
312
|
+
self.creation_time = creation_time
|
|
313
|
+
self.pending = pending
|
|
314
|
+
self.running = running
|
|
315
|
+
self.succeed = succeed
|
|
316
|
+
self.failed = failed
|
|
317
|
+
self.completion_time = completion_time
|
|
318
|
+
|
|
319
|
+
async def create_task(self, input_data: TaskInput) -> Task:
|
|
320
|
+
"""Create a new task in the session."""
|
|
321
|
+
task_spec = TaskSpec(
|
|
322
|
+
session_id=self.id,
|
|
323
|
+
input=input_data
|
|
324
|
+
)
|
|
325
|
+
|
|
326
|
+
request = CreateTaskRequest(task=task_spec)
|
|
327
|
+
|
|
328
|
+
try:
|
|
329
|
+
response = await self.connection._frontend.CreateTask(request)
|
|
330
|
+
|
|
331
|
+
return Task(
|
|
332
|
+
id=response.metadata.id,
|
|
333
|
+
session_id=self.id,
|
|
334
|
+
state=TaskState(response.status.state),
|
|
335
|
+
creation_time=datetime.fromtimestamp(response.status.creation_time),
|
|
336
|
+
input=input_data,
|
|
337
|
+
completion_time=datetime.fromtimestamp(response.status.completion_time) if response.status.HasField('completion_time') else None
|
|
338
|
+
)
|
|
339
|
+
|
|
340
|
+
except grpc.RpcError as e:
|
|
341
|
+
raise FlameError(
|
|
342
|
+
FlameErrorCode.INTERNAL,
|
|
343
|
+
f"failed to create task: {e.details()}"
|
|
344
|
+
)
|
|
345
|
+
|
|
346
|
+
async def get_task(self, task_id: TaskID) -> Task:
|
|
347
|
+
"""Get a task by ID."""
|
|
348
|
+
request = GetTaskRequest(
|
|
349
|
+
task_id=task_id,
|
|
350
|
+
session_id=self.id
|
|
351
|
+
)
|
|
352
|
+
|
|
353
|
+
try:
|
|
354
|
+
response = await self.connection._frontend.GetTask(request)
|
|
355
|
+
|
|
356
|
+
return Task(
|
|
357
|
+
id=response.metadata.id,
|
|
358
|
+
session_id=self.id,
|
|
359
|
+
state=TaskState(response.status.state),
|
|
360
|
+
creation_time=datetime.fromtimestamp(response.status.creation_time),
|
|
361
|
+
input=response.spec.input,
|
|
362
|
+
output=response.spec.output,
|
|
363
|
+
completion_time=datetime.fromtimestamp(response.status.completion_time) if response.status.HasField('completion_time') else None
|
|
364
|
+
)
|
|
365
|
+
|
|
366
|
+
except grpc.RpcError as e:
|
|
367
|
+
raise FlameError(
|
|
368
|
+
FlameErrorCode.INTERNAL,
|
|
369
|
+
f"failed to get task: {e.details()}"
|
|
370
|
+
)
|
|
371
|
+
|
|
372
|
+
async def watch_task(self, task_id: TaskID) -> "TaskWatcher":
|
|
373
|
+
"""Watch a task for updates."""
|
|
374
|
+
request = WatchTaskRequest(
|
|
375
|
+
task_id=task_id,
|
|
376
|
+
session_id=self.id
|
|
377
|
+
)
|
|
378
|
+
|
|
379
|
+
try:
|
|
380
|
+
stream = self.connection._frontend.WatchTask(request)
|
|
381
|
+
return TaskWatcher(stream)
|
|
382
|
+
|
|
383
|
+
except grpc.RpcError as e:
|
|
384
|
+
raise FlameError(
|
|
385
|
+
FlameErrorCode.INTERNAL,
|
|
386
|
+
f"failed to watch task: {e.details()}"
|
|
387
|
+
)
|
|
388
|
+
|
|
389
|
+
async def invoke(self, input_data: TaskInput, informer: Optional[TaskInformer] = None) -> Task:
|
|
390
|
+
"""Invoke a task with the given input and optional informer."""
|
|
391
|
+
task = await self.create_task(input_data)
|
|
392
|
+
watcher = await self.watch_task(task.id)
|
|
393
|
+
|
|
394
|
+
async for task in watcher:
|
|
395
|
+
if informer:
|
|
396
|
+
informer.on_update(task)
|
|
397
|
+
if task.is_completed():
|
|
398
|
+
return task
|
|
399
|
+
|
|
400
|
+
async def close(self) -> None:
|
|
401
|
+
"""Close the session."""
|
|
402
|
+
await self.connection.close_session(self.id)
|
|
403
|
+
|
|
404
|
+
class TaskWatcher:
|
|
405
|
+
"""Async iterator for watching task updates."""
|
|
406
|
+
|
|
407
|
+
def __init__(self, stream):
|
|
408
|
+
self._stream = stream
|
|
409
|
+
|
|
410
|
+
def __aiter__(self):
|
|
411
|
+
return self
|
|
412
|
+
|
|
413
|
+
async def __anext__(self) -> Task:
|
|
414
|
+
try:
|
|
415
|
+
response = await self._stream.read()
|
|
416
|
+
|
|
417
|
+
return Task(
|
|
418
|
+
id=response.metadata.id,
|
|
419
|
+
session_id=response.spec.session_id,
|
|
420
|
+
state=TaskState(response.status.state),
|
|
421
|
+
creation_time=datetime.fromtimestamp(response.status.creation_time),
|
|
422
|
+
input=response.spec.input,
|
|
423
|
+
output=response.spec.output,
|
|
424
|
+
completion_time=datetime.fromtimestamp(response.status.completion_time) if response.status.HasField('completion_time') else None
|
|
425
|
+
)
|
|
426
|
+
|
|
427
|
+
except StopAsyncIteration:
|
|
428
|
+
raise
|
|
429
|
+
except Exception as e:
|
|
430
|
+
raise FlameError(
|
|
431
|
+
FlameErrorCode.INTERNAL,
|
|
432
|
+
f"failed to watch task: {str(e)}"
|
|
433
|
+
)
|
flamepy/frontend_pb2.py
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
|
3
|
+
# NO CHECKED-IN PROTOBUF GENCODE
|
|
4
|
+
# source: frontend.proto
|
|
5
|
+
# Protobuf Python Version: 6.31.1
|
|
6
|
+
"""Generated protocol buffer code."""
|
|
7
|
+
from google.protobuf import descriptor as _descriptor
|
|
8
|
+
from google.protobuf import descriptor_pool as _descriptor_pool
|
|
9
|
+
from google.protobuf import runtime_version as _runtime_version
|
|
10
|
+
from google.protobuf import symbol_database as _symbol_database
|
|
11
|
+
from google.protobuf.internal import builder as _builder
|
|
12
|
+
_runtime_version.ValidateProtobufRuntimeVersion(
|
|
13
|
+
_runtime_version.Domain.PUBLIC,
|
|
14
|
+
6,
|
|
15
|
+
31,
|
|
16
|
+
1,
|
|
17
|
+
'',
|
|
18
|
+
'frontend.proto'
|
|
19
|
+
)
|
|
20
|
+
# @@protoc_insertion_point(imports)
|
|
21
|
+
|
|
22
|
+
_sym_db = _symbol_database.Default()
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
import flamepy.types_pb2 as types__pb2
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0e\x66rontend.proto\x12\x05\x66lame\x1a\x0btypes.proto\"W\n\x1aRegisterApplicationRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12+\n\x0b\x61pplication\x18\x02 \x01(\x0b\x32\x16.flame.ApplicationSpec\",\n\x1cUnregisterApplicationRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\"U\n\x18UpdateApplicationRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12+\n\x0b\x61pplication\x18\x02 \x01(\x0b\x32\x16.flame.ApplicationSpec\"%\n\x15GetApplicationRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\"\x18\n\x16ListApplicationRequest\";\n\x14\x43reateSessionRequest\x12#\n\x07session\x18\x01 \x01(\x0b\x32\x12.flame.SessionSpec\"*\n\x14\x44\x65leteSessionRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\"(\n\x12OpenSessionRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\")\n\x13\x43loseSessionRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\"\'\n\x11GetSessionRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\"\x14\n\x12ListSessionRequest\"2\n\x11\x43reateTaskRequest\x12\x1d\n\x04task\x18\x01 \x01(\x0b\x32\x0f.flame.TaskSpec\"8\n\x11\x44\x65leteTaskRequest\x12\x0f\n\x07task_id\x18\x01 \x01(\t\x12\x12\n\nsession_id\x18\x02 \x01(\t\"5\n\x0eGetTaskRequest\x12\x0f\n\x07task_id\x18\x01 \x01(\t\x12\x12\n\nsession_id\x18\x02 \x01(\t\"7\n\x10WatchTaskRequest\x12\x0f\n\x07task_id\x18\x01 \x01(\t\x12\x12\n\nsession_id\x18\x02 \x01(\t2\xc7\x07\n\x08\x46rontend\x12I\n\x13RegisterApplication\x12!.flame.RegisterApplicationRequest\x1a\r.flame.Result\"\x00\x12M\n\x15UnregisterApplication\x12#.flame.UnregisterApplicationRequest\x1a\r.flame.Result\"\x00\x12\x45\n\x11UpdateApplication\x12\x1f.flame.UpdateApplicationRequest\x1a\r.flame.Result\"\x00\x12\x44\n\x0eGetApplication\x12\x1c.flame.GetApplicationRequest\x1a\x12.flame.Application\"\x00\x12J\n\x0fListApplication\x12\x1d.flame.ListApplicationRequest\x1a\x16.flame.ApplicationList\"\x00\x12>\n\rCreateSession\x12\x1b.flame.CreateSessionRequest\x1a\x0e.flame.Session\"\x00\x12>\n\rDeleteSession\x12\x1b.flame.DeleteSessionRequest\x1a\x0e.flame.Session\"\x00\x12:\n\x0bOpenSession\x12\x19.flame.OpenSessionRequest\x1a\x0e.flame.Session\"\x00\x12<\n\x0c\x43loseSession\x12\x1a.flame.CloseSessionRequest\x1a\x0e.flame.Session\"\x00\x12\x38\n\nGetSession\x12\x18.flame.GetSessionRequest\x1a\x0e.flame.Session\"\x00\x12>\n\x0bListSession\x12\x19.flame.ListSessionRequest\x1a\x12.flame.SessionList\"\x00\x12\x35\n\nCreateTask\x12\x18.flame.CreateTaskRequest\x1a\x0b.flame.Task\"\x00\x12\x35\n\nDeleteTask\x12\x18.flame.DeleteTaskRequest\x1a\x0b.flame.Task\"\x00\x12/\n\x07GetTask\x12\x15.flame.GetTaskRequest\x1a\x0b.flame.Task\"\x00\x12\x35\n\tWatchTask\x12\x17.flame.WatchTaskRequest\x1a\x0b.flame.Task\"\x00\x30\x01\x42&Z$github.com/flame-sh/flame/sdk/go/rpcb\x06proto3')
|
|
29
|
+
|
|
30
|
+
_globals = globals()
|
|
31
|
+
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
|
|
32
|
+
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'frontend_pb2', _globals)
|
|
33
|
+
if not _descriptor._USE_C_DESCRIPTORS:
|
|
34
|
+
_globals['DESCRIPTOR']._loaded_options = None
|
|
35
|
+
_globals['DESCRIPTOR']._serialized_options = b'Z$github.com/flame-sh/flame/sdk/go/rpc'
|
|
36
|
+
_globals['_REGISTERAPPLICATIONREQUEST']._serialized_start=38
|
|
37
|
+
_globals['_REGISTERAPPLICATIONREQUEST']._serialized_end=125
|
|
38
|
+
_globals['_UNREGISTERAPPLICATIONREQUEST']._serialized_start=127
|
|
39
|
+
_globals['_UNREGISTERAPPLICATIONREQUEST']._serialized_end=171
|
|
40
|
+
_globals['_UPDATEAPPLICATIONREQUEST']._serialized_start=173
|
|
41
|
+
_globals['_UPDATEAPPLICATIONREQUEST']._serialized_end=258
|
|
42
|
+
_globals['_GETAPPLICATIONREQUEST']._serialized_start=260
|
|
43
|
+
_globals['_GETAPPLICATIONREQUEST']._serialized_end=297
|
|
44
|
+
_globals['_LISTAPPLICATIONREQUEST']._serialized_start=299
|
|
45
|
+
_globals['_LISTAPPLICATIONREQUEST']._serialized_end=323
|
|
46
|
+
_globals['_CREATESESSIONREQUEST']._serialized_start=325
|
|
47
|
+
_globals['_CREATESESSIONREQUEST']._serialized_end=384
|
|
48
|
+
_globals['_DELETESESSIONREQUEST']._serialized_start=386
|
|
49
|
+
_globals['_DELETESESSIONREQUEST']._serialized_end=428
|
|
50
|
+
_globals['_OPENSESSIONREQUEST']._serialized_start=430
|
|
51
|
+
_globals['_OPENSESSIONREQUEST']._serialized_end=470
|
|
52
|
+
_globals['_CLOSESESSIONREQUEST']._serialized_start=472
|
|
53
|
+
_globals['_CLOSESESSIONREQUEST']._serialized_end=513
|
|
54
|
+
_globals['_GETSESSIONREQUEST']._serialized_start=515
|
|
55
|
+
_globals['_GETSESSIONREQUEST']._serialized_end=554
|
|
56
|
+
_globals['_LISTSESSIONREQUEST']._serialized_start=556
|
|
57
|
+
_globals['_LISTSESSIONREQUEST']._serialized_end=576
|
|
58
|
+
_globals['_CREATETASKREQUEST']._serialized_start=578
|
|
59
|
+
_globals['_CREATETASKREQUEST']._serialized_end=628
|
|
60
|
+
_globals['_DELETETASKREQUEST']._serialized_start=630
|
|
61
|
+
_globals['_DELETETASKREQUEST']._serialized_end=686
|
|
62
|
+
_globals['_GETTASKREQUEST']._serialized_start=688
|
|
63
|
+
_globals['_GETTASKREQUEST']._serialized_end=741
|
|
64
|
+
_globals['_WATCHTASKREQUEST']._serialized_start=743
|
|
65
|
+
_globals['_WATCHTASKREQUEST']._serialized_end=798
|
|
66
|
+
_globals['_FRONTEND']._serialized_start=801
|
|
67
|
+
_globals['_FRONTEND']._serialized_end=1768
|
|
68
|
+
# @@protoc_insertion_point(module_scope)
|