Files
pipelinedb/examples/external-handler/main.go
2025-09-30 15:05:56 +08:00

180 lines
4.6 KiB
Go

// 演示如何使用外部处理器进行数据处理
package main
import (
"context"
"fmt"
"log"
"os"
"strings"
"time"
"code.tczkiot.com/wlw/pipelinedb"
)
// EmailProcessor 邮件处理器示例
type EmailProcessor struct {
name string
processed int
}
func NewEmailProcessor(name string) *EmailProcessor {
return &EmailProcessor{
name: name,
processed: 0,
}
}
// WillWarm 预热阶段:验证邮件格式
func (ep *EmailProcessor) WillWarm(ctx context.Context, group string, data []byte) ([]byte, error) {
fmt.Printf("🔥 [%s] 预热处理 - 组: %s\n", ep.name, group)
email := string(data)
// 简单的邮件格式验证
if !strings.Contains(email, "@") {
return nil, fmt.Errorf("无效的邮件格式: %s", email)
}
// 标准化邮件地址(转为小写)
normalizedEmail := strings.ToLower(strings.TrimSpace(email))
fmt.Printf(" 📧 邮件验证通过: %s -> %s\n", email, normalizedEmail)
// 模拟处理时间
time.Sleep(10 * time.Millisecond)
return []byte(normalizedEmail), nil
}
// WillCold 冷却阶段:发送邮件通知
func (ep *EmailProcessor) WillCold(ctx context.Context, group string, data []byte) ([]byte, error) {
fmt.Printf("❄️ [%s] 冷却处理 - 组: %s\n", ep.name, group)
email := string(data)
// 模拟发送邮件
fmt.Printf(" 📮 发送邮件到: %s\n", email)
fmt.Printf(" 📝 邮件内容: 您的数据已成功处理完成\n")
// 模拟发送时间
time.Sleep(50 * time.Millisecond)
ep.processed++
fmt.Printf(" ✅ 邮件发送成功 (已处理 %d 封邮件)\n", ep.processed)
return data, nil
}
// OnComplete 完成回调:统计处理结果
func (ep *EmailProcessor) OnComplete(ctx context.Context, group string) error {
fmt.Printf("🎉 [%s] 组处理完成 - 组: %s\n", ep.name, group)
fmt.Printf(" 📊 本组共处理邮件: %d 封\n", ep.processed)
// 重置计数器
ep.processed = 0
return nil
}
func main() {
// 创建临时数据库文件
dbFile := "handler_example.db"
defer os.Remove(dbFile)
// 确保文件可以创建
if _, err := os.Create(dbFile); err != nil {
log.Fatalf("创建数据库文件失败: %v", err)
}
fmt.Println("🚀 外部处理器示例")
fmt.Println("==================")
// 创建邮件处理器
emailHandler := NewEmailProcessor("邮件处理器")
// 打开数据库并配置处理器
fmt.Println("\n📂 步骤1: 配置数据库和处理器")
config := &pipelinedb.Config{
CacheSize: 50,
}
pdb, err := pipelinedb.Open(pipelinedb.Options{
Filename: dbFile,
Config: config,
Handler: emailHandler,
})
if err != nil {
log.Fatalf("打开数据库失败: %v", err)
}
defer pdb.Stop()
fmt.Printf("✅ 数据库已配置外部处理器: %s\n", emailHandler.name)
// 接收邮件数据
fmt.Println("\n📥 步骤2: 接收邮件数据")
emails := []string{
"user1@example.com",
"USER2@EXAMPLE.COM", // 测试大小写转换
"user3@test.org",
"invalid-email", // 测试无效邮件
"admin@company.net",
}
for i, email := range emails {
fmt.Printf("\n📧 处理邮件 %d: %s\n", i+1, email)
recordID, err := pdb.AcceptData("邮件处理", []byte(email),
fmt.Sprintf(`{"batch": %d, "source": "web_form"}`, i+1))
if err != nil {
fmt.Printf(" ❌ 接收失败: %v\n", err)
continue
}
fmt.Printf(" ✅ 记录ID: %d\n", recordID)
}
// 等待处理完成
fmt.Println("\n⏳ 步骤3: 等待处理完成")
fmt.Println("正在处理数据,请稍候...")
// 给处理器一些时间来处理数据
time.Sleep(2 * time.Second)
// 查看处理结果
fmt.Println("\n🔍 步骤4: 查看处理结果")
pageReq := &pipelinedb.PageRequest{
Page: 1,
PageSize: 20,
}
response, err := pdb.GetRecordsByGroup("邮件处理", pageReq)
if err != nil {
log.Fatalf("查询记录失败: %v", err)
}
fmt.Printf("📊 处理结果统计:\n")
fmt.Printf(" 总记录数: %d\n", response.TotalCount)
statusCount := make(map[pipelinedb.DataStatus]int)
for _, record := range response.Records {
statusCount[record.Status]++
}
fmt.Printf(" 状态分布:\n")
fmt.Printf(" 热数据 (hot): %d\n", statusCount[pipelinedb.StatusHot])
fmt.Printf(" 温数据 (warm): %d\n", statusCount[pipelinedb.StatusWarm])
fmt.Printf(" 冷数据 (cold): %d\n", statusCount[pipelinedb.StatusCold])
// 显示详细记录
fmt.Println("\n📋 详细记录:")
for _, record := range response.Records {
fmt.Printf(" ID:%d [%s] %s\n",
record.ID, record.Status, string(record.Data))
}
fmt.Println("\n🎉 外部处理器示例完成!")
fmt.Println("💡 提示: 查看上面的日志,可以看到数据如何通过预热->冷却的完整流程")
}