mirror of
https://github.com/oarkflow/mq.git
synced 2025-09-27 04:15:52 +08:00
276 lines
6.7 KiB
Go
276 lines
6.7 KiB
Go
package handlers
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"strings"
|
|
|
|
"github.com/oarkflow/json"
|
|
"github.com/oarkflow/mq"
|
|
"github.com/oarkflow/mq/dag"
|
|
)
|
|
|
|
// SplitHandler handles string split operations
|
|
type SplitHandler struct {
|
|
dag.Operation
|
|
}
|
|
|
|
func (h *SplitHandler) ProcessTask(ctx context.Context, task *mq.Task) mq.Result {
|
|
data, err := dag.UnmarshalPayload[map[string]any](ctx, task.Payload)
|
|
if err != nil {
|
|
return mq.Result{Error: fmt.Errorf("failed to unmarshal task payload: %w", err), Ctx: ctx}
|
|
}
|
|
|
|
operation, ok := h.Payload.Data["operation"].(string)
|
|
if !ok {
|
|
return mq.Result{Error: fmt.Errorf("operation not specified")}
|
|
}
|
|
|
|
var result map[string]any
|
|
switch operation {
|
|
case "split":
|
|
result = h.splitOperation(data)
|
|
case "split_to_array":
|
|
result = h.splitToArrayOperation(data)
|
|
default:
|
|
return mq.Result{Error: fmt.Errorf("unsupported operation: %s", operation)}
|
|
}
|
|
|
|
resultPayload, err := json.Marshal(result)
|
|
if err != nil {
|
|
return mq.Result{Error: fmt.Errorf("failed to marshal result: %w", err)}
|
|
}
|
|
|
|
return mq.Result{Payload: resultPayload, Ctx: ctx}
|
|
}
|
|
|
|
func (h *SplitHandler) splitOperation(data map[string]any) map[string]any {
|
|
result := make(map[string]any)
|
|
fields := h.getTargetFields()
|
|
separator := h.getSeparator()
|
|
targetField := h.getTargetField()
|
|
|
|
fmt.Printf("Split Operation: Fields=%v, Separator='%s', TargetField='%s'\n", fields, separator, targetField)
|
|
|
|
// Copy all original data
|
|
for key, value := range data {
|
|
result[key] = value
|
|
}
|
|
|
|
var allParts []string
|
|
for _, field := range fields {
|
|
if val, ok := data[field]; ok {
|
|
if str, ok := val.(string); ok {
|
|
parts := strings.Split(str, separator)
|
|
|
|
fmt.Printf("Splitting field '%s': Original='%s', Parts=%v\n", field, str, parts)
|
|
|
|
// Create individual fields for each part
|
|
for i, part := range parts {
|
|
result[fmt.Sprintf("%s_%d", field, i)] = strings.TrimSpace(part)
|
|
allParts = append(allParts, strings.TrimSpace(part))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Store all parts in the target field
|
|
result[targetField] = allParts
|
|
|
|
return result
|
|
}
|
|
|
|
func (h *SplitHandler) splitToArrayOperation(data map[string]any) map[string]any {
|
|
result := make(map[string]any)
|
|
fields := h.getTargetFields()
|
|
separator := h.getSeparator()
|
|
|
|
// Copy all original data
|
|
for key, value := range data {
|
|
result[key] = value
|
|
}
|
|
|
|
for _, field := range fields {
|
|
if val, ok := data[field]; ok {
|
|
if str, ok := val.(string); ok {
|
|
parts := strings.Split(str, separator)
|
|
var cleanParts []interface{}
|
|
for _, part := range parts {
|
|
cleanParts = append(cleanParts, strings.TrimSpace(part))
|
|
}
|
|
result[field+"_array"] = cleanParts
|
|
}
|
|
}
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
func (h *SplitHandler) getTargetFields() []string {
|
|
if fields, ok := h.Payload.Data["fields"].([]string); ok {
|
|
return fields
|
|
}
|
|
if fields, ok := h.Payload.Data["fields"].([]interface{}); ok {
|
|
var result []string
|
|
for _, field := range fields {
|
|
if str, ok := field.(string); ok {
|
|
result = append(result, str)
|
|
}
|
|
}
|
|
return result
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (h *SplitHandler) getTargetField() string {
|
|
if field, ok := h.Payload.Data["target_field"].(string); ok {
|
|
return field
|
|
}
|
|
return "split_result" // Default target field
|
|
}
|
|
|
|
func (h *SplitHandler) getSeparator() string {
|
|
if sep, ok := h.Payload.Data["separator"].(string); ok {
|
|
return sep
|
|
}
|
|
return "," // Default separator
|
|
}
|
|
|
|
func NewSplitHandler(id string) *SplitHandler {
|
|
return &SplitHandler{
|
|
Operation: dag.Operation{ID: id, Key: "split", Type: dag.Function, Tags: []string{"data", "transformation", "string"}},
|
|
}
|
|
}
|
|
|
|
// JoinHandler handles string join operations
|
|
type JoinHandler struct {
|
|
dag.Operation
|
|
}
|
|
|
|
func (h *JoinHandler) ProcessTask(ctx context.Context, task *mq.Task) mq.Result {
|
|
data, err := dag.UnmarshalPayload[map[string]any](ctx, task.Payload)
|
|
if err != nil {
|
|
return mq.Result{Error: fmt.Errorf("failed to unmarshal task payload: %w", err), Ctx: ctx}
|
|
}
|
|
|
|
operation, ok := h.Payload.Data["operation"].(string)
|
|
if !ok {
|
|
return mq.Result{Error: fmt.Errorf("operation not specified")}
|
|
}
|
|
|
|
var result map[string]any
|
|
switch operation {
|
|
case "join":
|
|
result = h.joinOperation(data)
|
|
case "join_from_array":
|
|
result = h.joinFromArrayOperation(data)
|
|
default:
|
|
return mq.Result{Error: fmt.Errorf("unsupported operation: %s", operation)}
|
|
}
|
|
|
|
resultPayload, err := json.Marshal(result)
|
|
if err != nil {
|
|
return mq.Result{Error: fmt.Errorf("failed to marshal result: %w", err)}
|
|
}
|
|
|
|
return mq.Result{Payload: resultPayload, Ctx: ctx}
|
|
}
|
|
|
|
func (h *JoinHandler) joinOperation(data map[string]any) map[string]any {
|
|
result := make(map[string]any)
|
|
targetField := h.getTargetField()
|
|
separator := h.getSeparator()
|
|
sourceFields := h.getSourceFields()
|
|
|
|
fmt.Printf("Join Operation: TargetField='%s', Separator='%s', SourceFields=%v\n", targetField, separator, sourceFields)
|
|
|
|
// Copy all original data
|
|
for key, value := range data {
|
|
result[key] = value
|
|
}
|
|
|
|
var parts []string
|
|
for _, field := range sourceFields {
|
|
if val, ok := data[field]; ok && val != nil {
|
|
parts = append(parts, fmt.Sprintf("%v", val))
|
|
}
|
|
}
|
|
|
|
fmt.Printf("Joining fields: Parts=%v\n", parts)
|
|
|
|
if len(parts) > 0 {
|
|
result[targetField] = strings.Join(parts, separator)
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
func (h *JoinHandler) joinFromArrayOperation(data map[string]any) map[string]any {
|
|
result := make(map[string]any)
|
|
targetField := h.getTargetField()
|
|
separator := h.getSeparator()
|
|
sourceField := h.getSourceField()
|
|
|
|
// Copy all original data
|
|
for key, value := range data {
|
|
result[key] = value
|
|
}
|
|
|
|
if val, ok := data[sourceField]; ok {
|
|
if arr, ok := val.([]interface{}); ok {
|
|
var parts []string
|
|
for _, item := range arr {
|
|
if item != nil {
|
|
parts = append(parts, fmt.Sprintf("%v", item))
|
|
}
|
|
}
|
|
result[targetField] = strings.Join(parts, separator)
|
|
}
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
func (h *JoinHandler) getTargetField() string {
|
|
if field, ok := h.Payload.Data["target_field"].(string); ok {
|
|
return field
|
|
}
|
|
return "joined_field"
|
|
}
|
|
|
|
func (h *JoinHandler) getSourceField() string {
|
|
if field, ok := h.Payload.Data["source_field"].(string); ok {
|
|
return field
|
|
}
|
|
return ""
|
|
}
|
|
|
|
func (h *JoinHandler) getSourceFields() []string {
|
|
if fields, ok := h.Payload.Data["source_fields"].([]string); ok {
|
|
return fields
|
|
}
|
|
if fields, ok := h.Payload.Data["source_fields"].([]interface{}); ok {
|
|
var result []string
|
|
for _, field := range fields {
|
|
if str, ok := field.(string); ok {
|
|
result = append(result, str)
|
|
}
|
|
}
|
|
return result
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (h *JoinHandler) getSeparator() string {
|
|
if sep, ok := h.Payload.Data["separator"].(string); ok {
|
|
return sep
|
|
}
|
|
return "," // Default separator
|
|
}
|
|
|
|
func NewJoinHandler(id string) *JoinHandler {
|
|
return &JoinHandler{
|
|
Operation: dag.Operation{ID: id, Key: "join", Type: dag.Function, Tags: []string{"data", "transformation", "string"}},
|
|
}
|
|
}
|