{"id":31052809,"url":"https://github.com/uptutu/bimawen","last_synced_at":"2026-07-06T22:31:05.523Z","repository":{"id":313175425,"uuid":"1050332086","full_name":"uptutu/bimawen","owner":"uptutu","description":null,"archived":false,"fork":false,"pushed_at":"2025-09-04T09:32:13.000Z","size":128,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-09-04T11:32:21.305Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/uptutu.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-09-04T09:28:52.000Z","updated_at":"2025-09-04T09:32:16.000Z","dependencies_parsed_at":"2025-09-04T11:32:23.204Z","dependency_job_id":"e93c400e-4e18-46d1-b6e1-b48447a4a58c","html_url":"https://github.com/uptutu/bimawen","commit_stats":null,"previous_names":["uptutu/bimawen"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/uptutu/bimawen","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/uptutu%2Fbimawen","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/uptutu%2Fbimawen/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/uptutu%2Fbimawen/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/uptutu%2Fbimawen/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/uptutu","download_url":"https://codeload.github.com/uptutu/bimawen/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/uptutu%2Fbimawen/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":275193588,"owners_count":25421409,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-14T02:00:10.474Z","response_time":75,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-09-15T01:24:40.361Z","updated_at":"2025-10-25T23:50:38.046Z","avatar_url":"https://github.com/uptutu.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Bimawen - 通用 MQ 工具库\n\nBimawen 是一个用 Go 编写的通用消息队列工具库，支持多种 MQ 系统，提供统一的 API 接口。\n\n## 特性\n\n- 🔌 **统一接口**: 通过 URI 字符串自动识别并连接不同的 MQ 系统\n- 🔄 **重试机制**: 内置指数退避重试策略\n- ⚡ **异步支持**: 支持同步和异步消息发送\n- 📦 **批量操作**: 支持批量发送消息\n- 🎯 **并发控制**: 可配置的消费者并发数\n- 🔧 **可扩展**: 支持自定义序列化器\n- 📈 **生产就绪**: 包含连接管理、健康检查等生产环境必需功能\n\n## 支持的 MQ 系统\n\n- **RabbitMQ** - 使用官方 `github.com/rabbitmq/amqp091-go`\n- **Redis** - 使用热门 `github.com/redis/go-redis/v9`\n\n## 安装\n\n```bash\ngo get local.git/libs/bimawen.git\n```\n\n## 快速开始\n\n### RabbitMQ 示例\n\n```go\npackage main\n\nimport (\n    \"context\"\n    \"log\"\n    \"time\"\n\n    \"local.git/libs/bimawen.git\"\n)\n\nfunc main() {\n    ctx := context.Background()\n\n    // 创建生产者\n    producer, err := bimawen.NewProducer(\"amqp://guest:guest@localhost:5672/\")\n    if err != nil {\n        log.Fatal(err)\n    }\n    defer producer.Close()\n\n    // 发送消息\n    message := \u0026bimawen.Message{\n        ID:        \"msg-001\",\n        Body:      []byte(`{\"order_id\": \"12345\", \"amount\": 100.50}`),\n        Headers:   map[string]interface{}{\"source\": \"order-service\"},\n        Timestamp: time.Now(),\n        Priority:  1,\n    }\n\n    err = producer.Send(ctx, \"orders\", message)\n    if err != nil {\n        log.Fatal(err)\n    }\n\n    // 创建消费者\n    consumer, err := bimawen.NewConsumer(\"amqp://guest:guest@localhost:5672/\")\n    if err != nil {\n        log.Fatal(err)\n    }\n    defer consumer.Close()\n\n    // 消费消息\n    err = consumer.Consume(ctx, \"orders\", func(ctx context.Context, msg *bimawen.Message) error {\n        log.Printf(\"Received: %s\", string(msg.Body))\n        return nil\n    })\n}\n```\n\n### Redis 示例\n\n```go\npackage main\n\nimport (\n    \"context\"\n    \"log\"\n    \"time\"\n\n    \"local.git/libs/bimawen.git\"\n)\n\nfunc main() {\n    ctx := context.Background()\n\n    // 创建生产者 (Redis)\n    producer, err := bimawen.NewProducer(\"redis://localhost:6379/0\")\n    if err != nil {\n        log.Fatal(err)\n    }\n    defer producer.Close()\n\n    // 发送延迟消息\n    message := \u0026bimawen.Message{\n        ID:        \"delayed-msg-001\",\n        Body:      []byte(`{\"reminder\": \"Meeting in 5 minutes\"}`),\n        Timestamp: time.Now(),\n        Delay:     5 * time.Second, // 延迟 5 秒\n    }\n\n    err = producer.Send(ctx, \"notifications\", message)\n    if err != nil {\n        log.Fatal(err)\n    }\n\n    // 批量发送\n    messages := []*bimawen.Message{\n        {ID: \"batch-1\", Body: []byte(`{\"data\": 1}`), Timestamp: time.Now()},\n        {ID: \"batch-2\", Body: []byte(`{\"data\": 2}`), Timestamp: time.Now()},\n        {ID: \"batch-3\", Body: []byte(`{\"data\": 3}`), Timestamp: time.Now()},\n    }\n\n    err = producer.SendBatch(ctx, \"batch-queue\", messages)\n    if err != nil {\n        log.Fatal(err)\n    }\n}\n```\n\n## API 文档\n\n### 核心接口\n\n#### Producer\n\n```go\ntype Producer interface {\n    // Send 同步发送消息\n    Send(ctx context.Context, topic string, message *Message) error\n    \n    // SendAsync 异步发送消息，返回错误通道\n    SendAsync(ctx context.Context, topic string, message *Message) \u003c-chan error\n    \n    // SendBatch 批量发送消息\n    SendBatch(ctx context.Context, topic string, messages []*Message) error\n    \n    // Close 关闭生产者\n    Close() error\n}\n```\n\n#### Consumer\n\n```go\ntype Consumer interface {\n    // Consume 开始消费消息\n    Consume(ctx context.Context, topic string, handler MessageHandler) error\n    \n    // ConsumeWithOptions 使用选项消费消息\n    ConsumeWithOptions(ctx context.Context, topic string, handler MessageHandler, opts *ConsumeOptions) error\n    \n    // Close 关闭消费者\n    Close() error\n}\n```\n\n#### Message\n\n```go\ntype Message struct {\n    ID            string                 // 消息唯一标识\n    Topic         string                 // 主题/队列名\n    Body          []byte                 // 消息体\n    Headers       map[string]interface{} // 消息头\n    Timestamp     time.Time              // 时间戳\n    DeliveryCount int                    // 投递次数\n    Priority      uint8                  // 优先级 (0-255)\n    TTL           time.Duration          // 生存时间\n    Delay         time.Duration          // 延迟时间\n}\n```\n\n### 配置选项\n\n#### 生产者配置\n\n```go\nopts := \u0026bimawen.ProducerOptions{\n    Timeout:     30 * time.Second,\n    RetryConfig: bimawen.DefaultRetryConfig(),\n    BatchSize:   100,\n    Serializer:  bimawen.NewJSONSerializer(),\n}\n\nproducer, err := bimawen.NewProducer(\"amqp://...\", opts)\n```\n\n#### RabbitMQ 交换机配置\n\nRabbitMQ 支持通过 `DriverOptions` 配置交换机和发布选项：\n\n```go\n// 配置 RabbitMQ 生产者使用指定交换机\nopts := bimawen.DefaultProducerOptions()\nopts.DriverOptions = map[string]interface{}{\n    bimawen.RabbitMQExchange:  \"my-direct-exchange\",  // 交换机名称\n    bimawen.RabbitMQMandatory: false,                 // 强制投递标志\n    bimawen.RabbitMQImmediate: false,                 // 立即投递标志\n}\n\nproducer, err := bimawen.NewProducer(\"amqp://guest:guest@localhost:5672/\", opts)\nif err != nil {\n    log.Fatal(err)\n}\n\n// 发送消息到指定交换机和路由键\nmessage := \u0026bimawen.Message{\n    ID:        \"msg-001\",\n    Body:      []byte(`{\"order_id\": \"12345\"}`),\n    Timestamp: time.Now(),\n}\n\n// 消息将发送到 \"my-direct-exchange\" 交换机，路由键为 \"order.created\"\nerr = producer.Send(ctx, \"order.created\", message)\n```\n\n**支持的 RabbitMQ 配置选项：**\n\n- **`bimawen.RabbitMQExchange`** (`\"exchange\"`): 交换机名称 (默认: `\"\"` 使用默认交换机)\n- **`bimawen.RabbitMQMandatory`** (`\"mandatory\"`): 强制投递标志 (默认: `false`)\n- **`bimawen.RabbitMQImmediate`** (`\"immediate\"`): 立即投递标志 (默认: `false`)\n\n**交换机类型使用场景：**\n\n```go\n// Direct 交换机 - 精确匹配路由键\nopts.DriverOptions[bimawen.RabbitMQExchange] = \"orders-direct\"\nproducer.Send(ctx, \"order.created\", message)  // 路由到绑定 \"order.created\" 的队列\n\n// Topic 交换机 - 模式匹配路由键\nopts.DriverOptions[bimawen.RabbitMQExchange] = \"orders-topic\" \nproducer.Send(ctx, \"order.payment.success\", message)  // 匹配 \"order.*\" 或 \"*.success\" 模式\n\n// Fanout 交换机 - 广播到所有绑定队列\nopts.DriverOptions[bimawen.RabbitMQExchange] = \"orders-fanout\"\nproducer.Send(ctx, \"\", message)  // 路由键被忽略，发送到所有绑定队列\n\n// 默认交换机 - 路由键必须与队列名完全匹配\nopts.DriverOptions[bimawen.RabbitMQExchange] = \"\"\nproducer.Send(ctx, \"order-queue\", message)  // 直接发送到名为 \"order-queue\" 的队列\n```\n\n#### 消费者配置\n\n```go\nopts := \u0026bimawen.ConsumerOptions{\n    Concurrency: 10,\n    AutoAck:     false,\n    RetryConfig: bimawen.DefaultRetryConfig(),\n}\n\nconsumer, err := bimawen.NewConsumer(\"redis://...\", opts)\n```\n\n### 重试配置\n\n```go\nretryConfig := \u0026bimawen.RetryConfig{\n    MaxRetries:          5,\n    InitialInterval:     1 * time.Second,\n    MaxInterval:        30 * time.Second,\n    Multiplier:          2.0,\n    RandomizationFactor: 0.1,\n}\n```\n\n## URI 格式\n\n### RabbitMQ\n\n```\namqp://[username:password@]host[:port][/vhost][?options]\namqps://[username:password@]host[:port][/vhost][?options]\n```\n\n示例:\n- `amqp://guest:guest@localhost:5672/`\n- `amqps://user:pass@rabbitmq.example.com:5671/myapp`\n\n### Redis\n\n```\nredis://[username:password@]host[:port][/database][?options]\nrediss://[username:password@]host[:port][/database][?options]\n```\n\n示例:\n- `redis://localhost:6379/0`\n- `rediss://user:pass@redis.example.com:6380/1?timeout=5s`\n\n## 高级功能\n\n### 自定义序列化器\n\n```go\ntype CustomSerializer struct{}\n\nfunc (s *CustomSerializer) Serialize(data interface{}) ([]byte, error) {\n    // 自定义序列化逻辑\n    return []byte{}, nil\n}\n\nfunc (s *CustomSerializer) Deserialize(data []byte, v interface{}) error {\n    // 自定义反序列化逻辑\n    return nil\n}\n\nfunc (s *CustomSerializer) ContentType() string {\n    return \"application/custom\"\n}\n\n// 注册自定义序列化器\nbimawen.DefaultSerializerRegistry.Register(\"custom\", \u0026CustomSerializer{})\n```\n\n### 错误处理\n\n```go\n// 创建可重试错误\nretryableErr := bimawen.NewRetryableError(errors.New(\"temporary failure\"))\n\n// 创建不可重试错误  \nnonRetryableErr := bimawen.NewNonRetryableError(errors.New(\"permanent failure\"))\n\n// 检查是否可重试\nif bimawen.IsRetryableError(err) {\n    // 可以重试\n}\n```\n\n### 健康检查\n\n```go\n// 通过工厂创建驱动进行健康检查\ndriver, err := bimawen.DefaultDriverFactory.Create(\"amqp://localhost:5672\")\nif err != nil {\n    log.Fatal(err)\n}\ndefer driver.Close()\n\nctx := context.Background()\nif err := driver.HealthCheck(ctx); err != nil {\n    log.Printf(\"Health check failed: %v\", err)\n}\n```\n\n## 连接对象访问接口\n\nBimawen 提供类型安全的连接对象访问接口，让您可以直接使用底层驱动的原生功能。\n\n### RabbitMQ 连接访问\n\n```go\n// 获取生产者的底层 AMQP 连接对象\nproducer, err := bimawen.NewProducer(\"amqp://guest:guest@localhost:5672/\")\nif err != nil {\n    log.Fatal(err)\n}\ndefer producer.Close()\n\n// 类型断言获取 RabbitMQ 连接访问器\nif accessor, ok := producer.(bimawen.RabbitMQConnectionAccessor); ok {\n    // 获取 AMQP 通道进行直接操作\n    channel := accessor.GetChannel()\n    if channel != nil {\n        // 使用原生 AMQP 功能\n        err := channel.ExchangeDeclare(\"my-exchange\", \"direct\", false, false, false, false, nil)\n        if err != nil {\n            log.Printf(\"Exchange declaration failed: %v\", err)\n        }\n        // 通道会自动返回到连接池\n    }\n    \n    // 获取 AMQP 连接进行高级管理\n    connection := accessor.GetConnection()\n    if connection != nil \u0026\u0026 !connection.IsClosed() {\n        log.Println(\"Connection is healthy\")\n    }\n}\n```\n\n### Redis 连接访问\n\n```go\n// 获取生产者的底层 Redis 客户端\nproducer, err := bimawen.NewProducer(\"redis://localhost:6379/0\")\nif err != nil {\n    log.Fatal(err)\n}\ndefer producer.Close()\n\n// 类型断言获取 Redis 连接访问器\nif accessor, ok := producer.(bimawen.RedisConnectionAccessor); ok {\n    client := accessor.GetClient()\n    if client != nil {\n        // 使用原生 Redis 功能\n        ctx := context.Background()\n        result := client.Set(ctx, \"my-key\", \"my-value\", time.Hour)\n        if result.Err() != nil {\n            log.Printf(\"Redis SET failed: %v\", result.Err())\n        }\n        \n        // 获取值\n        val := client.Get(ctx, \"my-key\")\n        log.Printf(\"Retrieved value: %s\", val.Val())\n    }\n}\n```\n\n### Redis Streams 连接访问\n\n```go\n// 获取 Redis Streams 生产者的底层客户端\nproducer, err := bimawen.NewProducer(\"redis-streams://localhost:6379/0\")\nif err != nil {\n    log.Fatal(err)\n}\ndefer producer.Close()\n\n// 类型断言获取 Redis Streams 连接访问器\nif accessor, ok := producer.(bimawen.RedisStreamsConnectionAccessor); ok {\n    client := accessor.GetClient()\n    if client != nil {\n        // 使用原生 Redis Streams 功能\n        ctx := context.Background()\n        result := client.XAdd(ctx, \u0026redis.XAddArgs{\n            Stream: \"my-stream\",\n            ID:     \"*\",\n            Values: map[string]interface{}{\n                \"field1\": \"value1\",\n                \"field2\": \"value2\",\n            },\n        })\n        \n        if result.Err() == nil {\n            log.Printf(\"Added to stream with ID: %s\", result.Val())\n        }\n    }\n}\n```\n\n### 连接访问接口特性\n\n- **类型安全**: 每种驱动都有专门的接口，避免使用 `any` 或类型判断\n- **连接池集成**: 自动与现有连接池集成，无需手动管理连接生命周期\n- **线程安全**: 所有连接访问操作都是并发安全的\n- **资源管理**: 连接和通道会自动返回到池中重复使用\n- **统一接口**: 生产者和消费者都支持相同的连接访问接口\n\n## 最佳实践\n\n1. **连接管理**: 重用生产者和消费者实例，避免频繁创建和销毁\n2. **错误处理**: 区分可重试和不可重试的错误\n3. **资源清理**: 始终调用 `Close()` 方法清理资源\n4. **并发控制**: 根据系统负载调整消费者并发数\n5. **超时设置**: 为操作设置合理的超时时间\n6. **消息确认**: 谨慎使用 `AutoAck`，确保消息处理完成后再确认\n\n## 测试\n\n```bash\n# 运行测试\ngo test -v\n\n# 运行示例\ngo run example/main.go\n```\n\n## 许可证\n\nMIT License","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fuptutu%2Fbimawen","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fuptutu%2Fbimawen","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fuptutu%2Fbimawen/lists"}