maas-task-backoff-framework


Namemaas-task-backoff-framework JSON
Version 1.0.3 PyPI version JSON
download
home_pagehttps://github.com/xiaofucoding/maas-task-backoff-framework.git/
Summary基于Redis的任务退避重试、调度框架,支持多种退避策略
upload_time2025-09-09 03:37:59
maintainerNone
docs_urlNone
authorxinzf
requires_python>=3.7
licenseMIT
keywords task retry backoff redis queue
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # 任务退避重试、调度框架

[![Python](https://img.shields.io/badge/Python-3-blue.svg)](https://www.python.org/)
[![License](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)

一个基于Redis的分布式任务退避重试、调度框架,支持多种退避策略和并发执行。

## ✨ 核心特性

- 🔄 **多种退避策略**: 固定间隔、指数退避、线性退避
- 🚀 **高并发执行**: 支持线程池/进程池并发处理
- 📊 **任务优先级**: 支持任务优先级管理
- ⏱️ **超时控制**: 任务执行超时和失败处理
- 📈 **状态监控**: 完整的任务状态管理和监控
- 🎯 **灵活调度**: 可配置的定时调度间隔
- 🔒 **分布式锁**: 基于Redis的分布式任务队列
- 💾 **存储方式**: 目前只支持 Redis,后续会增加MySQL、达梦数据库等支持

## 📚设计思路


### 业务架构设计

![](http://fire-blog.oss-cn-beijing.aliyuncs.com//images/20250909113017.png)

### 退避工具内部组件设计


![](http://fire-blog.oss-cn-beijing.aliyuncs.com//images/20250909113043.png)

### 设计类图

![](http://fire-blog.oss-cn-beijing.aliyuncs.com//images/20250909113102.png)

### 调用时序图

用户提交task

![](http://fire-blog.oss-cn-beijing.aliyuncs.com//images/20250909113117.png)

调度执行task

![](http://fire-blog.oss-cn-beijing.aliyuncs.com//images/20250909113543.png)

## 📦 安装

```bash
pip install maas-task-backoff-framework
```

## 🚀 快速开始

### 使用示例

```python
from backoff.scheduler.backoff_scheduler import (
    TaskBackoffScheduler,
    TaskBackoffConfig,
    TaskEntity,
    TaskConfig,
    StorageConfig,
    ThreadPoolConfig,
    SchedulerConfig,
    ResultEntity,
)

# 1. 创建配置
config = TaskBackoffConfig()

# Redis存储配置
config.storage = StorageConfig(
    type="redis", 
    host="localhost", 
    port=6379, 
    database=0, 
    password=""
)

# 任务配置
config.task = TaskConfig(
    biz_prefix="my_service",
    batch_size=10,
    max_retry_count=3,
    backoff_strategy="exponential",
    backoff_interval=30,
    backoff_multiplier=2.0,
    min_gpu_memory_gb=0.5,
    min_gpu_utilization=10
)

# 线程池配置
config.threadpool = ThreadPoolConfig(
    concurrency=5, 
    exec_timeout=300, 
    proc_mode="process"
)

# 调度器配置
config.scheduler = SchedulerConfig(interval=10)

# 2. 创建调度器
scheduler = TaskBackoffScheduler(config)

# 3. 定义任务处理器
def task_handler(task: TaskEntity):
    # 您的业务逻辑
    print(f"处理任务: {task.task_id}")
    return ResultEntity.ok(
        result={"status": "success", "data": "处理完成"},
        task_id=task.task_id,
    )

def exception_handler(task: TaskEntity):
    # 异常处理逻辑
    return ResultEntity.fail(
        code=-1,
        message="任务执行失败",
        task_id=task.task_id,
    )

# 4. 注册处理器
scheduler.set_custom_task_handler(task_handler)

scheduler.set_custom_task_exception_handler(exception_handler)

# 5. 启动调度器(如果不需要启动调度器,请忽略此步骤,只提供基础的Task API操作)
scheduler.start()
```

## 💻 Task任务数据结构

```python
{
    "task_id": "task_5775520148",
    "process": 0,
    "status": "pending",
    "result": "",
    "param": "{\"index\": 111, \"data\": \"test_data\"}",
    "retry_count": 0,
    "next_execution_time": 0,
    "create_time": 1756695076,
    "update_time": 1756695076,
    "max_retry_count": 5,
    "backoff_strategy": "fixed",
    "backoff_interval": 60,
    "backoff_multiplier": 2.0,
    "min_gpu_memory_gb": 0,
    "min_gpu_utilization": 0.0,
    "biz_prefix": "custom_scheduling_example"
}
```

结果字段说明

|字段     | 类型   |  说明           |
|----------|--------|----------------|
| task_id     | string |  任务唯一id     |
| biz_prefix     | string |  任务的业务前缀    |
| process     | int |  任务进度  |
| status     | string    |  任务状态      |
| result | string    | 任务的执行结果    |
| param | string |   任务的参数      |
| retry_count | int |   重试次数      |
| next_execution_time | int |   下次执行时间 |
| create_time | int |   创建时间      |
| update_time | int |   更新时间      |
| max_retry_count | int |   最大重试次数      |
| backoff_strategy | string |   退避类型      |
| backoff_interval | int |   退避间隔      |
| backoff_multiplier | int |      退避倍数   |
| min_gpu_memory_gb | int |      需要的最小GPU内存   |
| min_gpu_utilization | int |      需要的最小GPU使用率   |


## 📚 API 参考

### 任务管理

#### 1.创建任务

创建任务可选权重值 `score` , 不传默认会以为当前时间为权重值先进先出;`score` 越小越先执行

```python
scheduler.create_task(
    task_params={"key": "value"},
    task_id="unique_task_id",
    score=100
) -> Tuple[bool, message: str]
```

参数字段说明
| 字段     | 类型 | 必填   |  说明           |
|----------|--------|--------|----------------|
| task_params     |是| dict |  任务的业务参数     |
| task_id     | 是 |string |  自定义的任务id    |
| score     |否| int |  权重值(不传默认会以为当前时间为权重值先进先出;越小越先执行)  |


#### 2.查询任务

```python
scheduler.get_task(task_id) -> TaskEntity
```

#### 3.撤销任务

- 线程模式下撤销任务仅会变更任务状态为 `canceled`,等待任务执行完成

- 进程模式下会直接取消正在运行中的任务并变更任务状态

```python
scheduler.cancel_task(task_id) -> Tuple[bool, str]:
```

#### 4.获取队列统计

```python
scheduler.get_queue_statistics() -> Dict[str, int]:
```

队列统计结构返回结果示例

```python
{
    "system_status": {
        "update_time": "2025-09-01 15:30:13"
    },
    "tasks": {
        "pending": {
            "total": 34,
            "queue": [
                "task_2728059290",
                "task_2829088805"
            ]
        },
        "processing": {
            "total": 0,
            "queue": []
        },
        "completed": {
            "total": 0,
            "queue": []
        },
        "failed": {
            "total": 0,
            "queue": []
        }
    }
}
```

字段说明
| 字段     | 类型   |  说明           |
|----------|--------|----------------|
| update_time     | string |  请求时间    |
| tasks     | object |  任务队列统计      |
| pending     | object |  等待队列      |
| processing     | object |  处理中队列      |
| completed     | object |  已完成队列      |
| failed     | object |  失败队列      |
| total     | int  |  任务队列成员总数      | 
| queue     | list |  任务成员列表      |


### 5.更任务状态

```python
# 标记任务完成
scheduler.mark_task_completed(task_id, "执行结果") -> bool

# 标记任务失败
scheduler.mark_task_failed(task_id, "失败原因") -> bool

# 标记任务处理中
scheduler.mark_task_processing(task_id) -> bool
```

### 6.更新任务进度

```python
# 更新任务进度
scheduler.update_task_progress(task_id, 75) -> bool # 75%
```

### 7.调度器控制

如果不显示执行 `scheduler.start()` 则不会启动定时调度,只提供 Task API 的基础操作

```python
# 启动调度器
scheduler.start()

# 关闭调度器
scheduler.shutdown()
```

### 8.处理器管理

- 任务处理器 ( `set_custom_task_handler` ): 可选设置,处理正常的业务逻辑

- 异常处理器 ( `set_custom_task_exception_handler` ): 可选设置,处理任务执行过程中的异常情况

```python
# 注册任务处理器(可选)
scheduler.set_custom_task_handler(task_handler)

# 注册异常处理器(可选)
scheduler.set_custom_task_exception_handler(exception_handler)
```

**处理器函数签名**

处理器参数必须为 `TaskEntity` ,响应类型必须为 `ResultEntity`

```python
from backoff.scheduler.backoff_scheduler import (
    TaskEntity,
    ResultEntity,
)
def task_handler(task: TaskEntity) -> ResultEntity:
    # 您的业务逻辑
    pass

def exception_handler(task: TaskEntity) -> ResultEntity:
    # 异常处理逻辑
    pass
```

#### 返回值示例

**成功处理:**

```python
return ResultEntity.ok(
    result={"status": "success", "data": "处理结果"},
    task_id=task.task_id,
)
```

**失败处理:**
```python
return ResultEntity.fail(
    code=-1,
    message="任务执行失败",
    result={"error": "具体错误信息"},
    task_id=task.task_id,
)
```


## ⚙️ 配置详解

### StorageConfig (存储配置)

| 参数     | 类型   | 必填 | 默认值    | 说明           |
|----------|--------|------|-----------|----------------|
| type     | string | 是   | redis     | 存储类型,目前仅支持Redis      |
| host     | string | 是   |  localhost| Redis主机地址  |
| port     | int    | 是   | 6379      | Redis端口      |
| database | int    | 否   | 0         | Redis数据库    |
| password | string | 否   | ""        | Redis密码      |

**type 存储类型:**

- `redis` : 默认
- `mysql` : 暂未支持
- `达梦` : 暂未支持

### TaskConfig (任务配置)

| 参数                | 类型   | 必填 | 默认值        | 说明                    |
|---------------------|--------|------|---------------|-------------------------|
| biz_prefix          | string | **是**   | -         | 业务唯一标识               |
| max_retry_count     | int    | 否   | 3             | 最大重试次数            |
| backoff_strategy    | string | 否   | exponential   | 退避策略                |
| backoff_interval    | int    | 否   | 30            | 初始退避间隔(秒)        |
| backoff_multiplier  | float  | 否   | 2.0           | 退避倍数                |
| batch_size          | int    | 否   | 100           | 批次大小                |
| min_gpu_memory_gb   | float  | 否   | 0             | 最小GPU内存(GB)         |
| min_gpu_utilization | int    | 否   | 0             | 最小GPU利用率(%)        |

**backoff_strategy 退避策略说明:**

- `exponential` : 指数退避 (默认)
- `fixed` : 固定间隔重试
- `linear` : 线性退避

### ThreadPoolConfig (线程池配置)

| 参数          | 类型   | 必填 | 默认值 | 说明                    |
|---------------|--------|------|--------|-------------------------|
| concurrency   | int    | 否   | 10     | 并发线程/进程数         |
| proc_mode     | string | 否   | process | 执行模式                |
| exec_timeout  | int    | 否   | 300    | 任务超时时间(秒)        |

**proc_mode 执行模式说明:**

- `thread` : 线程池模式
- `process` : 进程池模式 (默认)

线程池模式,一旦线程启动后,线程将会持续运行,直到执行完毕,线程将被回收。

进程池模式,如果进程内业务异常或者超时等待,进程将被收回。

### SchedulerConfig (调度器配置)

| 参数     | 类型 | 必填 | 默认值 | 说明           |
|----------|------|------|--------|----------------|
| interval | int  | 否   | 10     | 轮询间隔(秒)   |






            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/xiaofucoding/maas-task-backoff-framework.git/",
    "name": "maas-task-backoff-framework",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.7",
    "maintainer_email": null,
    "keywords": "task retry backoff redis queue",
    "author": "xinzf",
    "author_email": "515361725@qq.com",
    "download_url": "https://files.pythonhosted.org/packages/10/bb/a7fd7419691dac1b3da57ed13f4d9a1c1619f818e0824ee0821428e55d0a/maas-task-backoff-framework-1.0.3.tar.gz",
    "platform": null,
    "description": "# \u4efb\u52a1\u9000\u907f\u91cd\u8bd5\u3001\u8c03\u5ea6\u6846\u67b6\n\n[![Python](https://img.shields.io/badge/Python-3-blue.svg)](https://www.python.org/)\n[![License](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)\n\n\u4e00\u4e2a\u57fa\u4e8eRedis\u7684\u5206\u5e03\u5f0f\u4efb\u52a1\u9000\u907f\u91cd\u8bd5\u3001\u8c03\u5ea6\u6846\u67b6\uff0c\u652f\u6301\u591a\u79cd\u9000\u907f\u7b56\u7565\u548c\u5e76\u53d1\u6267\u884c\u3002\n\n## \u2728 \u6838\u5fc3\u7279\u6027\n\n- \ud83d\udd04 **\u591a\u79cd\u9000\u907f\u7b56\u7565**: \u56fa\u5b9a\u95f4\u9694\u3001\u6307\u6570\u9000\u907f\u3001\u7ebf\u6027\u9000\u907f\n- \ud83d\ude80 **\u9ad8\u5e76\u53d1\u6267\u884c**: \u652f\u6301\u7ebf\u7a0b\u6c60/\u8fdb\u7a0b\u6c60\u5e76\u53d1\u5904\u7406\n- \ud83d\udcca **\u4efb\u52a1\u4f18\u5148\u7ea7**: \u652f\u6301\u4efb\u52a1\u4f18\u5148\u7ea7\u7ba1\u7406\n- \u23f1\ufe0f **\u8d85\u65f6\u63a7\u5236**: \u4efb\u52a1\u6267\u884c\u8d85\u65f6\u548c\u5931\u8d25\u5904\u7406\n- \ud83d\udcc8 **\u72b6\u6001\u76d1\u63a7**: \u5b8c\u6574\u7684\u4efb\u52a1\u72b6\u6001\u7ba1\u7406\u548c\u76d1\u63a7\n- \ud83c\udfaf **\u7075\u6d3b\u8c03\u5ea6**: \u53ef\u914d\u7f6e\u7684\u5b9a\u65f6\u8c03\u5ea6\u95f4\u9694\n- \ud83d\udd12 **\u5206\u5e03\u5f0f\u9501**: \u57fa\u4e8eRedis\u7684\u5206\u5e03\u5f0f\u4efb\u52a1\u961f\u5217\n- \ud83d\udcbe **\u5b58\u50a8\u65b9\u5f0f**: \u76ee\u524d\u53ea\u652f\u6301 Redis\uff0c\u540e\u7eed\u4f1a\u589e\u52a0MySQL\u3001\u8fbe\u68a6\u6570\u636e\u5e93\u7b49\u652f\u6301\n\n## \ud83d\udcda\u8bbe\u8ba1\u601d\u8def\n\n\n### \u4e1a\u52a1\u67b6\u6784\u8bbe\u8ba1\n\n![](http://fire-blog.oss-cn-beijing.aliyuncs.com//images/20250909113017.png)\n\n### \u9000\u907f\u5de5\u5177\u5185\u90e8\u7ec4\u4ef6\u8bbe\u8ba1\n\n\n![](http://fire-blog.oss-cn-beijing.aliyuncs.com//images/20250909113043.png)\n\n### \u8bbe\u8ba1\u7c7b\u56fe\n\n![](http://fire-blog.oss-cn-beijing.aliyuncs.com//images/20250909113102.png)\n\n### \u8c03\u7528\u65f6\u5e8f\u56fe\n\n\u7528\u6237\u63d0\u4ea4task\n\n![](http://fire-blog.oss-cn-beijing.aliyuncs.com//images/20250909113117.png)\n\n\u8c03\u5ea6\u6267\u884ctask\n\n![](http://fire-blog.oss-cn-beijing.aliyuncs.com//images/20250909113543.png)\n\n## \ud83d\udce6 \u5b89\u88c5\n\n```bash\npip install maas-task-backoff-framework\n```\n\n## \ud83d\ude80 \u5feb\u901f\u5f00\u59cb\n\n### \u4f7f\u7528\u793a\u4f8b\n\n```python\nfrom backoff.scheduler.backoff_scheduler import (\n    TaskBackoffScheduler,\n    TaskBackoffConfig,\n    TaskEntity,\n    TaskConfig,\n    StorageConfig,\n    ThreadPoolConfig,\n    SchedulerConfig,\n    ResultEntity,\n)\n\n# 1. \u521b\u5efa\u914d\u7f6e\nconfig = TaskBackoffConfig()\n\n# Redis\u5b58\u50a8\u914d\u7f6e\nconfig.storage = StorageConfig(\n    type=\"redis\", \n    host=\"localhost\", \n    port=6379, \n    database=0, \n    password=\"\"\n)\n\n# \u4efb\u52a1\u914d\u7f6e\nconfig.task = TaskConfig(\n    biz_prefix=\"my_service\",\n    batch_size=10,\n    max_retry_count=3,\n    backoff_strategy=\"exponential\",\n    backoff_interval=30,\n    backoff_multiplier=2.0,\n    min_gpu_memory_gb=0.5,\n    min_gpu_utilization=10\n)\n\n# \u7ebf\u7a0b\u6c60\u914d\u7f6e\nconfig.threadpool = ThreadPoolConfig(\n    concurrency=5, \n    exec_timeout=300, \n    proc_mode=\"process\"\n)\n\n# \u8c03\u5ea6\u5668\u914d\u7f6e\nconfig.scheduler = SchedulerConfig(interval=10)\n\n# 2. \u521b\u5efa\u8c03\u5ea6\u5668\nscheduler = TaskBackoffScheduler(config)\n\n# 3. \u5b9a\u4e49\u4efb\u52a1\u5904\u7406\u5668\ndef task_handler(task: TaskEntity):\n    # \u60a8\u7684\u4e1a\u52a1\u903b\u8f91\n    print(f\"\u5904\u7406\u4efb\u52a1: {task.task_id}\")\n    return ResultEntity.ok(\n        result={\"status\": \"success\", \"data\": \"\u5904\u7406\u5b8c\u6210\"},\n        task_id=task.task_id,\n    )\n\ndef exception_handler(task: TaskEntity):\n    # \u5f02\u5e38\u5904\u7406\u903b\u8f91\n    return ResultEntity.fail(\n        code=-1,\n        message=\"\u4efb\u52a1\u6267\u884c\u5931\u8d25\",\n        task_id=task.task_id,\n    )\n\n# 4. \u6ce8\u518c\u5904\u7406\u5668\nscheduler.set_custom_task_handler(task_handler)\n\nscheduler.set_custom_task_exception_handler(exception_handler)\n\n# 5. \u542f\u52a8\u8c03\u5ea6\u5668\uff08\u5982\u679c\u4e0d\u9700\u8981\u542f\u52a8\u8c03\u5ea6\u5668\uff0c\u8bf7\u5ffd\u7565\u6b64\u6b65\u9aa4\uff0c\u53ea\u63d0\u4f9b\u57fa\u7840\u7684Task API\u64cd\u4f5c\uff09\nscheduler.start()\n```\n\n## \ud83d\udcbb Task\u4efb\u52a1\u6570\u636e\u7ed3\u6784\n\n```python\n{\n    \"task_id\": \"task_5775520148\",\n    \"process\": 0,\n    \"status\": \"pending\",\n    \"result\": \"\",\n    \"param\": \"{\\\"index\\\": 111, \\\"data\\\": \\\"test_data\\\"}\",\n    \"retry_count\": 0,\n    \"next_execution_time\": 0,\n    \"create_time\": 1756695076,\n    \"update_time\": 1756695076,\n    \"max_retry_count\": 5,\n    \"backoff_strategy\": \"fixed\",\n    \"backoff_interval\": 60,\n    \"backoff_multiplier\": 2.0,\n    \"min_gpu_memory_gb\": 0,\n    \"min_gpu_utilization\": 0.0,\n    \"biz_prefix\": \"custom_scheduling_example\"\n}\n```\n\n\u7ed3\u679c\u5b57\u6bb5\u8bf4\u660e\n\n|\u5b57\u6bb5     | \u7c7b\u578b   |  \u8bf4\u660e           |\n|----------|--------|----------------|\n| task_id     | string |  \u4efb\u52a1\u552f\u4e00id     |\n| biz_prefix     | string |  \u4efb\u52a1\u7684\u4e1a\u52a1\u524d\u7f00    |\n| process     | int |  \u4efb\u52a1\u8fdb\u5ea6  |\n| status     | string    |  \u4efb\u52a1\u72b6\u6001      |\n| result | string    | \u4efb\u52a1\u7684\u6267\u884c\u7ed3\u679c    |\n| param | string |   \u4efb\u52a1\u7684\u53c2\u6570      |\n| retry_count | int |   \u91cd\u8bd5\u6b21\u6570      |\n| next_execution_time | int |   \u4e0b\u6b21\u6267\u884c\u65f6\u95f4 |\n| create_time | int |   \u521b\u5efa\u65f6\u95f4      |\n| update_time | int |   \u66f4\u65b0\u65f6\u95f4      |\n| max_retry_count | int |   \u6700\u5927\u91cd\u8bd5\u6b21\u6570      |\n| backoff_strategy | string |   \u9000\u907f\u7c7b\u578b      |\n| backoff_interval | int |   \u9000\u907f\u95f4\u9694      |\n| backoff_multiplier | int |      \u9000\u907f\u500d\u6570   |\n| min_gpu_memory_gb | int |      \u9700\u8981\u7684\u6700\u5c0fGPU\u5185\u5b58   |\n| min_gpu_utilization | int |      \u9700\u8981\u7684\u6700\u5c0fGPU\u4f7f\u7528\u7387   |\n\n\n## \ud83d\udcda API \u53c2\u8003\n\n### \u4efb\u52a1\u7ba1\u7406\n\n#### 1.\u521b\u5efa\u4efb\u52a1\n\n\u521b\u5efa\u4efb\u52a1\u53ef\u9009\u6743\u91cd\u503c `score` , \u4e0d\u4f20\u9ed8\u8ba4\u4f1a\u4ee5\u4e3a\u5f53\u524d\u65f6\u95f4\u4e3a\u6743\u91cd\u503c\u5148\u8fdb\u5148\u51fa\uff1b`score` \u8d8a\u5c0f\u8d8a\u5148\u6267\u884c\n\n```python\nscheduler.create_task(\n    task_params={\"key\": \"value\"},\n    task_id=\"unique_task_id\",\n    score=100\n) -> Tuple[bool, message: str]\n```\n\n\u53c2\u6570\u5b57\u6bb5\u8bf4\u660e\n| \u5b57\u6bb5     | \u7c7b\u578b | \u5fc5\u586b   |  \u8bf4\u660e           |\n|----------|--------|--------|----------------|\n| task_params     |\u662f| dict |  \u4efb\u52a1\u7684\u4e1a\u52a1\u53c2\u6570     |\n| task_id     | \u662f |string |  \u81ea\u5b9a\u4e49\u7684\u4efb\u52a1id    |\n| score     |\u5426| int |  \u6743\u91cd\u503c\uff08\u4e0d\u4f20\u9ed8\u8ba4\u4f1a\u4ee5\u4e3a\u5f53\u524d\u65f6\u95f4\u4e3a\u6743\u91cd\u503c\u5148\u8fdb\u5148\u51fa\uff1b\u8d8a\u5c0f\u8d8a\u5148\u6267\u884c\uff09  |\n\n\n#### 2.\u67e5\u8be2\u4efb\u52a1\n\n```python\nscheduler.get_task(task_id) -> TaskEntity\n```\n\n#### 3.\u64a4\u9500\u4efb\u52a1\n\n- \u7ebf\u7a0b\u6a21\u5f0f\u4e0b\u64a4\u9500\u4efb\u52a1\u4ec5\u4f1a\u53d8\u66f4\u4efb\u52a1\u72b6\u6001\u4e3a `canceled`\uff0c\u7b49\u5f85\u4efb\u52a1\u6267\u884c\u5b8c\u6210\n\n- \u8fdb\u7a0b\u6a21\u5f0f\u4e0b\u4f1a\u76f4\u63a5\u53d6\u6d88\u6b63\u5728\u8fd0\u884c\u4e2d\u7684\u4efb\u52a1\u5e76\u53d8\u66f4\u4efb\u52a1\u72b6\u6001\n\n```python\nscheduler.cancel_task(task_id) -> Tuple[bool, str]:\n```\n\n#### 4.\u83b7\u53d6\u961f\u5217\u7edf\u8ba1\n\n```python\nscheduler.get_queue_statistics() -> Dict[str, int]:\n```\n\n\u961f\u5217\u7edf\u8ba1\u7ed3\u6784\u8fd4\u56de\u7ed3\u679c\u793a\u4f8b\n\n```python\n{\n    \"system_status\": {\n        \"update_time\": \"2025-09-01 15:30:13\"\n    },\n    \"tasks\": {\n        \"pending\": {\n            \"total\": 34,\n            \"queue\": [\n                \"task_2728059290\",\n                \"task_2829088805\"\n            ]\n        },\n        \"processing\": {\n            \"total\": 0,\n            \"queue\": []\n        },\n        \"completed\": {\n            \"total\": 0,\n            \"queue\": []\n        },\n        \"failed\": {\n            \"total\": 0,\n            \"queue\": []\n        }\n    }\n}\n```\n\n\u5b57\u6bb5\u8bf4\u660e\n| \u5b57\u6bb5     | \u7c7b\u578b   |  \u8bf4\u660e           |\n|----------|--------|----------------|\n| update_time     | string |  \u8bf7\u6c42\u65f6\u95f4    |\n| tasks     | object |  \u4efb\u52a1\u961f\u5217\u7edf\u8ba1      |\n| pending     | object |  \u7b49\u5f85\u961f\u5217      |\n| processing     | object |  \u5904\u7406\u4e2d\u961f\u5217      |\n| completed     | object |  \u5df2\u5b8c\u6210\u961f\u5217      |\n| failed     | object |  \u5931\u8d25\u961f\u5217      |\n| total     | int  |  \u4efb\u52a1\u961f\u5217\u6210\u5458\u603b\u6570      | \n| queue     | list |  \u4efb\u52a1\u6210\u5458\u5217\u8868      |\n\n\n### 5.\u66f4\u4efb\u52a1\u72b6\u6001\n\n```python\n# \u6807\u8bb0\u4efb\u52a1\u5b8c\u6210\nscheduler.mark_task_completed(task_id, \"\u6267\u884c\u7ed3\u679c\") -> bool\n\n# \u6807\u8bb0\u4efb\u52a1\u5931\u8d25\nscheduler.mark_task_failed(task_id, \"\u5931\u8d25\u539f\u56e0\") -> bool\n\n# \u6807\u8bb0\u4efb\u52a1\u5904\u7406\u4e2d\nscheduler.mark_task_processing(task_id) -> bool\n```\n\n### 6.\u66f4\u65b0\u4efb\u52a1\u8fdb\u5ea6\n\n```python\n# \u66f4\u65b0\u4efb\u52a1\u8fdb\u5ea6\nscheduler.update_task_progress(task_id, 75) -> bool # 75%\n```\n\n### 7.\u8c03\u5ea6\u5668\u63a7\u5236\n\n\u5982\u679c\u4e0d\u663e\u793a\u6267\u884c `scheduler.start()` \u5219\u4e0d\u4f1a\u542f\u52a8\u5b9a\u65f6\u8c03\u5ea6\uff0c\u53ea\u63d0\u4f9b Task API \u7684\u57fa\u7840\u64cd\u4f5c\n\n```python\n# \u542f\u52a8\u8c03\u5ea6\u5668\nscheduler.start()\n\n# \u5173\u95ed\u8c03\u5ea6\u5668\nscheduler.shutdown()\n```\n\n### 8.\u5904\u7406\u5668\u7ba1\u7406\n\n- \u4efb\u52a1\u5904\u7406\u5668 ( `set_custom_task_handler` ): \u53ef\u9009\u8bbe\u7f6e\uff0c\u5904\u7406\u6b63\u5e38\u7684\u4e1a\u52a1\u903b\u8f91\n\n- \u5f02\u5e38\u5904\u7406\u5668 ( `set_custom_task_exception_handler` ): \u53ef\u9009\u8bbe\u7f6e\uff0c\u5904\u7406\u4efb\u52a1\u6267\u884c\u8fc7\u7a0b\u4e2d\u7684\u5f02\u5e38\u60c5\u51b5\n\n```python\n# \u6ce8\u518c\u4efb\u52a1\u5904\u7406\u5668\uff08\u53ef\u9009\uff09\nscheduler.set_custom_task_handler(task_handler)\n\n# \u6ce8\u518c\u5f02\u5e38\u5904\u7406\u5668\uff08\u53ef\u9009\uff09\nscheduler.set_custom_task_exception_handler(exception_handler)\n```\n\n**\u5904\u7406\u5668\u51fd\u6570\u7b7e\u540d**\n\n\u5904\u7406\u5668\u53c2\u6570\u5fc5\u987b\u4e3a `TaskEntity` \uff0c\u54cd\u5e94\u7c7b\u578b\u5fc5\u987b\u4e3a `ResultEntity`\n\n```python\nfrom backoff.scheduler.backoff_scheduler import (\n    TaskEntity,\n    ResultEntity,\n)\ndef task_handler(task: TaskEntity) -> ResultEntity:\n    # \u60a8\u7684\u4e1a\u52a1\u903b\u8f91\n    pass\n\ndef exception_handler(task: TaskEntity) -> ResultEntity:\n    # \u5f02\u5e38\u5904\u7406\u903b\u8f91\n    pass\n```\n\n#### \u8fd4\u56de\u503c\u793a\u4f8b\n\n**\u6210\u529f\u5904\u7406:**\n\n```python\nreturn ResultEntity.ok(\n    result={\"status\": \"success\", \"data\": \"\u5904\u7406\u7ed3\u679c\"},\n    task_id=task.task_id,\n)\n```\n\n**\u5931\u8d25\u5904\u7406:**\n```python\nreturn ResultEntity.fail(\n    code=-1,\n    message=\"\u4efb\u52a1\u6267\u884c\u5931\u8d25\",\n    result={\"error\": \"\u5177\u4f53\u9519\u8bef\u4fe1\u606f\"},\n    task_id=task.task_id,\n)\n```\n\n\n## \u2699\ufe0f \u914d\u7f6e\u8be6\u89e3\n\n### StorageConfig (\u5b58\u50a8\u914d\u7f6e)\n\n| \u53c2\u6570     | \u7c7b\u578b   | \u5fc5\u586b | \u9ed8\u8ba4\u503c    | \u8bf4\u660e           |\n|----------|--------|------|-----------|----------------|\n| type     | string | \u662f   | redis     | \u5b58\u50a8\u7c7b\u578b\uff0c\u76ee\u524d\u4ec5\u652f\u6301Redis      |\n| host     | string | \u662f   |  localhost| Redis\u4e3b\u673a\u5730\u5740  |\n| port     | int    | \u662f   | 6379      | Redis\u7aef\u53e3      |\n| database | int    | \u5426   | 0         | Redis\u6570\u636e\u5e93    |\n| password | string | \u5426   | \"\"        | Redis\u5bc6\u7801      |\n\n**type \u5b58\u50a8\u7c7b\u578b:**\n\n- `redis` : \u9ed8\u8ba4\n- `mysql` : \u6682\u672a\u652f\u6301\n- `\u8fbe\u68a6` : \u6682\u672a\u652f\u6301\n\n### TaskConfig (\u4efb\u52a1\u914d\u7f6e)\n\n| \u53c2\u6570                | \u7c7b\u578b   | \u5fc5\u586b | \u9ed8\u8ba4\u503c        | \u8bf4\u660e                    |\n|---------------------|--------|------|---------------|-------------------------|\n| biz_prefix          | string | **\u662f**   | -         | \u4e1a\u52a1\u552f\u4e00\u6807\u8bc6               |\n| max_retry_count     | int    | \u5426   | 3             | \u6700\u5927\u91cd\u8bd5\u6b21\u6570            |\n| backoff_strategy    | string | \u5426   | exponential   | \u9000\u907f\u7b56\u7565                |\n| backoff_interval    | int    | \u5426   | 30            | \u521d\u59cb\u9000\u907f\u95f4\u9694(\u79d2)        |\n| backoff_multiplier  | float  | \u5426   | 2.0           | \u9000\u907f\u500d\u6570                |\n| batch_size          | int    | \u5426   | 100           | \u6279\u6b21\u5927\u5c0f                |\n| min_gpu_memory_gb   | float  | \u5426   | 0             | \u6700\u5c0fGPU\u5185\u5b58(GB)         |\n| min_gpu_utilization | int    | \u5426   | 0             | \u6700\u5c0fGPU\u5229\u7528\u7387(%)        |\n\n**backoff_strategy \u9000\u907f\u7b56\u7565\u8bf4\u660e:**\n\n- `exponential` : \u6307\u6570\u9000\u907f (\u9ed8\u8ba4)\n- `fixed` : \u56fa\u5b9a\u95f4\u9694\u91cd\u8bd5\n- `linear` : \u7ebf\u6027\u9000\u907f\n\n### ThreadPoolConfig (\u7ebf\u7a0b\u6c60\u914d\u7f6e)\n\n| \u53c2\u6570          | \u7c7b\u578b   | \u5fc5\u586b | \u9ed8\u8ba4\u503c | \u8bf4\u660e                    |\n|---------------|--------|------|--------|-------------------------|\n| concurrency   | int    | \u5426   | 10     | \u5e76\u53d1\u7ebf\u7a0b/\u8fdb\u7a0b\u6570         |\n| proc_mode     | string | \u5426   | process | \u6267\u884c\u6a21\u5f0f                |\n| exec_timeout  | int    | \u5426   | 300    | \u4efb\u52a1\u8d85\u65f6\u65f6\u95f4(\u79d2)        |\n\n**proc_mode \u6267\u884c\u6a21\u5f0f\u8bf4\u660e:**\n\n- `thread` : \u7ebf\u7a0b\u6c60\u6a21\u5f0f\n- `process` : \u8fdb\u7a0b\u6c60\u6a21\u5f0f (\u9ed8\u8ba4)\n\n\u7ebf\u7a0b\u6c60\u6a21\u5f0f\uff0c\u4e00\u65e6\u7ebf\u7a0b\u542f\u52a8\u540e\uff0c\u7ebf\u7a0b\u5c06\u4f1a\u6301\u7eed\u8fd0\u884c\uff0c\u76f4\u5230\u6267\u884c\u5b8c\u6bd5\uff0c\u7ebf\u7a0b\u5c06\u88ab\u56de\u6536\u3002\n\n\u8fdb\u7a0b\u6c60\u6a21\u5f0f\uff0c\u5982\u679c\u8fdb\u7a0b\u5185\u4e1a\u52a1\u5f02\u5e38\u6216\u8005\u8d85\u65f6\u7b49\u5f85\uff0c\u8fdb\u7a0b\u5c06\u88ab\u6536\u56de\u3002\n\n### SchedulerConfig (\u8c03\u5ea6\u5668\u914d\u7f6e)\n\n| \u53c2\u6570     | \u7c7b\u578b | \u5fc5\u586b | \u9ed8\u8ba4\u503c | \u8bf4\u660e           |\n|----------|------|------|--------|----------------|\n| interval | int  | \u5426   | 10     | \u8f6e\u8be2\u95f4\u9694(\u79d2)   |\n\n\n\n\n\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "\u57fa\u4e8eRedis\u7684\u4efb\u52a1\u9000\u907f\u91cd\u8bd5\u3001\u8c03\u5ea6\u6846\u67b6\uff0c\u652f\u6301\u591a\u79cd\u9000\u907f\u7b56\u7565",
    "version": "1.0.3",
    "project_urls": {
        "Bug Reports": "https://github.com/yourusername/task-backoff-scheduler/issues",
        "Documentation": "https://github.com/yourusername/task-backoff-scheduler#readme",
        "Homepage": "https://github.com/xiaofucoding/maas-task-backoff-framework.git/",
        "Source": "https://github.com/yourusername/task-backoff-scheduler"
    },
    "split_keywords": [
        "task",
        "retry",
        "backoff",
        "redis",
        "queue"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "8b45c81c7b01d414d7916b3f9e5767121befdb35f5c2315f2f3f84b582cb930d",
                "md5": "8dada3b3716613c55bb87b3ba1faa141",
                "sha256": "ab65065f55f1273bbb72bdedd3cb493b0e90daeacd3e0d96dcb0909c22fab84c"
            },
            "downloads": -1,
            "filename": "maas_task_backoff_framework-1.0.3-py2-none-any.whl",
            "has_sig": false,
            "md5_digest": "8dada3b3716613c55bb87b3ba1faa141",
            "packagetype": "bdist_wheel",
            "python_version": "py2",
            "requires_python": ">=3.7",
            "size": 41212,
            "upload_time": "2025-09-09T03:37:58",
            "upload_time_iso_8601": "2025-09-09T03:37:58.207665Z",
            "url": "https://files.pythonhosted.org/packages/8b/45/c81c7b01d414d7916b3f9e5767121befdb35f5c2315f2f3f84b582cb930d/maas_task_backoff_framework-1.0.3-py2-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "10bba7fd7419691dac1b3da57ed13f4d9a1c1619f818e0824ee0821428e55d0a",
                "md5": "2f3b705322608bfdfaba9e7ff0510d4d",
                "sha256": "34edb6b6450638a1eae7eff7b0d8f557833aed5c639ca2b12ae92173608c2f9d"
            },
            "downloads": -1,
            "filename": "maas-task-backoff-framework-1.0.3.tar.gz",
            "has_sig": false,
            "md5_digest": "2f3b705322608bfdfaba9e7ff0510d4d",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.7",
            "size": 29159,
            "upload_time": "2025-09-09T03:37:59",
            "upload_time_iso_8601": "2025-09-09T03:37:59.771719Z",
            "url": "https://files.pythonhosted.org/packages/10/bb/a7fd7419691dac1b3da57ed13f4d9a1c1619f818e0824ee0821428e55d0a/maas-task-backoff-framework-1.0.3.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-09-09 03:37:59",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "xiaofucoding",
    "github_project": "maas-task-backoff-framework",
    "github_not_found": true,
    "lcname": "maas-task-backoff-framework"
}
        
Elapsed time: 0.49520s