Skip to content

Commit e2b2d68

Browse files
author
zirongluo
committed
[update] add delete faas instance
1 parent 2184c33 commit e2b2d68

4 files changed

Lines changed: 146 additions & 7 deletions

File tree

‎dashscope/finetune/agentic_rl.py‎

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
# Copyright (c) Alibaba, Inc. and its affiliates.
55

6+
import time
67
from typing import Union, List, Optional, ClassVar, Dict, Any
78
from typing_extensions import Self
89

@@ -429,6 +430,8 @@ async def test_functions(
429430
api_key: str = None,
430431
pull_logs: bool = False,
431432
log_page_size: int = 100,
433+
start_time: Optional[int] = None,
434+
end_time: Optional[int] = None,
432435
):
433436
"""Test a deployed function instance with custom input data.
434437
@@ -442,6 +445,10 @@ async def test_functions(
442445
(with pagination) after verification and print them
443446
between separator markers.
444447
log_page_size: Page size used when pulling logs.
448+
start_time: Optional start time filter (in seconds) for log
449+
pulling. Defaults to 24 hours before ``end_time``.
450+
end_time: Optional end time filter (in seconds) for log
451+
pulling. Defaults to the current time (now).
445452
"""
446453
try:
447454
set_api_key(api_key)
@@ -475,6 +482,8 @@ async def test_functions(
475482
await cls._pull_function_instance_logs(
476483
function_instance_id=instance_id,
477484
page_size=log_page_size,
485+
start_time=start_time,
486+
end_time=end_time,
478487
)
479488

480489
return result
@@ -579,14 +588,61 @@ async def query_all_function_instance_logs(
579588
error_code=3010,
580589
) from e
581590

591+
@classmethod
592+
async def delete_function_instance(
593+
cls,
594+
function_instance_id: str,
595+
api_key: str = None,
596+
) -> Dict[str, Any]:
597+
"""Delete a function (faas) runtime instance.
598+
599+
Args:
600+
function_instance_id: Target function instance ID.
601+
api_key: DashScope API key (uses DASHSCOPE_API_KEY env var
602+
if omitted).
603+
604+
Returns:
605+
Raw response dict of the delete API, containing
606+
``data.status`` (e.g. "deleted") and
607+
``data.sandbox_code``.
608+
609+
Raises:
610+
InstanceQueryError: If the deletion fails.
611+
"""
612+
try:
613+
set_api_key(api_key)
614+
615+
fc_component = AgenticRLFunctionComponent
616+
return await fc_component.delete_function_instance(
617+
function_instance_id=function_instance_id,
618+
)
619+
620+
except Exception as e:
621+
if hasattr(e, "error_code"):
622+
raise
623+
raise InstanceQueryError(
624+
"Function instance deletion failed",
625+
error_code=3011,
626+
) from e
627+
582628
@classmethod
583629
async def _pull_function_instance_logs(
584630
cls,
585631
function_instance_id: str,
586632
page_size: int = 100,
633+
start_time: Optional[int] = None,
634+
end_time: Optional[int] = None,
587635
) -> None:
588636
"""Pull all logs of a function instance and print them between
589-
separator markers (best effort, never raises)."""
637+
separator markers (best effort, never raises).
638+
639+
When ``start_time``/``end_time`` are not provided, defaults to
640+
pulling logs from 24 hours ago until now.
641+
"""
642+
if end_time is None:
643+
end_time = int(time.time())
644+
if start_time is None:
645+
start_time = end_time - 24 * 60 * 60
590646
logger.info(
591647
"************start query log "
592648
f"(function_instance_id={function_instance_id})*******",
@@ -595,6 +651,8 @@ async def _pull_function_instance_logs(
595651
logs = await cls.query_all_function_instance_logs(
596652
function_instance_id=function_instance_id,
597653
page_size=page_size,
654+
start_time=start_time,
655+
end_time=end_time,
598656
)
599657
for entry in logs:
600658
logger.info(f"[function instance log] {entry}")

‎dashscope/finetune/reinforcement/__init__.py‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
DASHSCOPE_HTTP_BASE_URL,
1717
LOG_LEVEL,
1818
FC_API_KEY,
19+
FC_DELETE_API,
1920
FC_FILES_START,
2021
FC_LOAD_API,
2122
FC_PYPI_LIB,
@@ -155,6 +156,7 @@ def __getattr__(name):
155156
"DASHSCOPE_HTTP_BASE_URL",
156157
"LOG_LEVEL",
157158
"FC_API_KEY",
159+
"FC_DELETE_API",
158160
"FC_FILES_START",
159161
"FC_LOAD_API",
160162
"FC_PYPI_LIB",

‎dashscope/finetune/reinforcement/common/constants.py‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,10 @@ def get_int_env(env_var: str, default: int) -> int:
8787
"FC_QUERY_LOG_API",
8888
f"{FC_BASE_ENDPOINT}/query/faas/log",
8989
)
90+
FC_DELETE_API = os.environ.get(
91+
"FC_DELETE_API",
92+
f"{FC_BASE_ENDPOINT}/delete/faas",
93+
)
9094
FC_LAYER_CREATE_API = os.environ.get( # POST
9195
"FC_LAYER_CREATE_API",
9296
f"{FC_BASE_ENDPOINT}/create/faas/layer",

‎dashscope/finetune/reinforcement/common/model.py‎

Lines changed: 81 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
# Local Application
2626
from dashscope.finetune.reinforcement.common.constants import (
2727
FC_API_KEY,
28+
FC_DELETE_API,
2829
FC_LOAD_API,
2930
FC_QUERY_API,
3031
FC_QUERY_LOG_API,
@@ -1063,12 +1064,26 @@ def _extract_log_page(
10631064
) -> Tuple[List[str], Optional[int]]:
10641065
"""Extract log messages and total count from a log query response.
10651066
1066-
Expected response format::
1067+
Two payload shapes are supported. The DashScope gateway returns
1068+
snake_case keys under "output"::
1069+
1070+
{
1071+
"request_id": "...",
1072+
"output": {
1073+
"page_number": 1,
1074+
"page_size": 100,
1075+
"total_count": 86,
1076+
"log_entries": [
1077+
{"instance_id": "...", "message": "...",
1078+
"timestamp": 1699051200}
1079+
]
1080+
}
1081+
}
1082+
1083+
while the backend service returns camelCase keys under "data"::
10671084
10681085
{
10691086
"success": true,
1070-
"code": null,
1071-
"message": null,
10721087
"data": {
10731088
"pageNumber": 1,
10741089
"pageSize": 50,
@@ -1083,17 +1098,21 @@ def _extract_log_page(
10831098
Only the "message" field of each log entry is kept; other fields
10841099
are ignored.
10851100
"""
1086-
data = result.get("data", {})
1101+
data = result.get("output")
1102+
if not isinstance(data, Dict):
1103+
data = result.get("data")
10871104
if not isinstance(data, Dict):
10881105
return [], None
10891106

1090-
entries = data.get("logEntries") or []
1107+
entries = data.get("log_entries") or data.get("logEntries") or []
10911108
logs = [
10921109
entry.get("message", "") if isinstance(entry, Dict) else str(entry)
10931110
for entry in entries
10941111
]
10951112

1096-
total = data.get("totalCount")
1113+
total = data.get("total_count")
1114+
if total is None:
1115+
total = data.get("totalCount")
10971116
if not isinstance(total, int):
10981117
total = None
10991118

@@ -1216,6 +1235,62 @@ async def query_all_function_instance_logs(
12161235
)
12171236
return all_logs
12181237

1238+
@classmethod
1239+
async def delete_function_instance(
1240+
cls,
1241+
function_instance_id: str,
1242+
) -> Dict[str, Any]:
1243+
"""Delete a function (faas) runtime instance.
1244+
1245+
Args:
1246+
function_instance_id: Target function instance ID.
1247+
1248+
Returns:
1249+
Raw response dict of the delete API, e.g.::
1250+
1251+
{
1252+
"code": 0,
1253+
"message": "success",
1254+
"data": {
1255+
"status": "deleted",
1256+
"sandbox_code": "sandbox-xxx"
1257+
}
1258+
}
1259+
"""
1260+
if not function_instance_id:
1261+
raise InputError(
1262+
"No function instance ID available for deletion",
1263+
error_code=2074,
1264+
)
1265+
1266+
url = f"{FC_DELETE_API}/{function_instance_id}"
1267+
result = await client_fc(FC_API_KEY, url, {})
1268+
status = result.get("status", {})
1269+
if isinstance(status, Dict) and status.get("code", 200) != 200:
1270+
raise InstanceQueryError(
1271+
f"Function instance deletion failed: {result}",
1272+
error_code=2075,
1273+
instance_id=function_instance_id,
1274+
)
1275+
code = result.get("code")
1276+
if result.get("success") is False or (
1277+
code is not None and code not in (0, 200)
1278+
):
1279+
raise InstanceQueryError(
1280+
"Function instance deletion failed: "
1281+
f"{result.get('message') or result}",
1282+
error_code=2075,
1283+
instance_id=function_instance_id,
1284+
)
1285+
1286+
data = result.get("data", {})
1287+
status_value = data.get("status") if isinstance(data, Dict) else data
1288+
logger.info(
1289+
f"Function instance deleted | FunctionInstanceID: "
1290+
f"{function_instance_id} | Status: {status_value}",
1291+
)
1292+
return result
1293+
12191294

12201295
class RolloutFunctionComponent(AgenticRLFunctionComponent):
12211296
"""Rollout function component with type fixed as ROLLOUT."""

0 commit comments

Comments
 (0)