feat: wire Temporal gRPC into REST handler
- Handler now maintains gRPC connection to Temporal (port 7233)
- startWorkflow & describeWorkflow translated to actual gRPC calls
- Other 20+ operations phased in via TEMPORAL_GRPC_MIGRATION roadmap
- Updated docs: TEMPORAL_USAGE now describes gRPC architecture
- Added TEMPORAL_GRPC_MIGRATION.md for implementation reference
- Deleted WORKFLOWS.md (outdated duplicate)
Fixes: gRPC was imported but unused - now operational for START/DESCRIBE.
Verification: go build ./cmd/gateway ✅ (no errors)
This commit is contained in:
@@ -5,8 +5,13 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"go.temporal.io/api/common/v1"
|
||||
"go.temporal.io/api/taskqueue/v1"
|
||||
"go.temporal.io/api/workflowservice/v1"
|
||||
)
|
||||
|
||||
// RequestPayload represents the unified request format for all operations
|
||||
@@ -29,7 +34,8 @@ type ResponsePayload struct {
|
||||
|
||||
// Handler handles HTTP requests for Temporal operations
|
||||
type Handler struct {
|
||||
hostPort string // e.g., "localhost:7233"
|
||||
hostPort string // e.g., "localhost:7233"
|
||||
grpcClient *GRPCClient // gRPC connection to Temporal
|
||||
}
|
||||
|
||||
// NewHandler creates a new Temporal HTTP handler
|
||||
@@ -37,8 +43,16 @@ func NewHandler(hostPort string) *Handler {
|
||||
if hostPort == "" {
|
||||
hostPort = "localhost:7233"
|
||||
}
|
||||
|
||||
grpcClient, err := NewGRPCClient(hostPort)
|
||||
if err != nil {
|
||||
log.Printf("WARNING: Failed to connect to Temporal at %s: %v", hostPort, err)
|
||||
// Don't fail startup; operations will return errors
|
||||
}
|
||||
|
||||
return &Handler{
|
||||
hostPort: hostPort,
|
||||
hostPort: hostPort,
|
||||
grpcClient: grpcClient,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -266,6 +280,10 @@ func getMap(payload map[string]interface{}, key string) map[string]interface{} {
|
||||
// Workflow Operations
|
||||
|
||||
func (h *Handler) startWorkflow(ctx context.Context, namespace string, payload map[string]interface{}) (interface{}, string, string) {
|
||||
if h.grpcClient == nil {
|
||||
return nil, "TEMPORAL_UNAVAILABLE", "Temporal server connection not available"
|
||||
}
|
||||
|
||||
workflowID := getString(payload, "workflow_id")
|
||||
if workflowID == "" {
|
||||
return nil, "INVALID_REQUEST", "workflow_id is required"
|
||||
@@ -281,25 +299,64 @@ func (h *Handler) startWorkflow(ctx context.Context, namespace string, payload m
|
||||
return nil, "INVALID_REQUEST", "task_queue is required"
|
||||
}
|
||||
|
||||
// Would call Temporal WorkflowService.StartWorkflowExecution
|
||||
input := getMap(payload, "input")
|
||||
|
||||
req := &workflowservice.StartWorkflowExecutionRequest{
|
||||
Namespace: namespace,
|
||||
WorkflowId: workflowID,
|
||||
WorkflowType: &common.WorkflowType{Name: workflowType},
|
||||
TaskQueue: &taskqueue.TaskQueue{Name: taskQueue},
|
||||
}
|
||||
|
||||
if len(input) > 0 {
|
||||
inputBytes, _ := json.Marshal(input)
|
||||
req.Input = &common.Payloads{
|
||||
Payloads: []*common.Payload{{Data: inputBytes}},
|
||||
}
|
||||
}
|
||||
|
||||
resp, err := h.grpcClient.GetWorkflowServiceStub().StartWorkflowExecution(ctx, req)
|
||||
if err != nil {
|
||||
return nil, "TEMPORAL_UNAVAILABLE", fmt.Sprintf("failed to start workflow: %v", err)
|
||||
}
|
||||
|
||||
return map[string]interface{}{
|
||||
"workflow_id": workflowID,
|
||||
"run_id": fmt.Sprintf("run_%d", time.Now().UnixNano()),
|
||||
"run_id": resp.RunId,
|
||||
"start_time": time.Now(),
|
||||
}, "", ""
|
||||
}
|
||||
|
||||
func (h *Handler) describeWorkflow(ctx context.Context, namespace string, payload map[string]interface{}) (interface{}, string, string) {
|
||||
if h.grpcClient == nil {
|
||||
return nil, "TEMPORAL_UNAVAILABLE", "Temporal server connection not available"
|
||||
}
|
||||
|
||||
workflowID := getString(payload, "workflow_id")
|
||||
if workflowID == "" {
|
||||
return nil, "INVALID_REQUEST", "workflow_id is required"
|
||||
}
|
||||
|
||||
// Would call Temporal WorkflowService.DescribeWorkflowExecution
|
||||
runID := getString(payload, "run_id")
|
||||
|
||||
resp, err := h.grpcClient.GetWorkflowServiceStub().DescribeWorkflowExecution(ctx, &workflowservice.DescribeWorkflowExecutionRequest{
|
||||
Namespace: namespace,
|
||||
Execution: &common.WorkflowExecution{WorkflowId: workflowID, RunId: runID},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, "WORKFLOW_NOT_FOUND", fmt.Sprintf("failed to describe workflow: %v", err)
|
||||
}
|
||||
|
||||
status := "UNKNOWN"
|
||||
if resp.WorkflowExecutionInfo != nil {
|
||||
status = resp.WorkflowExecutionInfo.Status.String()
|
||||
}
|
||||
|
||||
return map[string]interface{}{
|
||||
"workflow_id": workflowID,
|
||||
"status": "RUNNING",
|
||||
"start_time": time.Now(),
|
||||
"run_id": runID,
|
||||
"status": status,
|
||||
"start_time": resp.WorkflowExecutionInfo.StartTime,
|
||||
}, "", ""
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user