package memory import ( "context" "fmt" "time" "go.temporal.io/sdk/activity" "go.temporal.io/sdk/temporal" "go.temporal.io/sdk/worker" "go.temporal.io/sdk/workflow" ) // RegisterMemoryActivities registers all memory service activities with worker func RegisterMemoryActivities(w worker.Worker, service *Service) { activities := NewActivities(service) // Register activities (activity name = "ActivityName" → "activityName") w.RegisterActivity(activities.CreateKnowledgeActivity) w.RegisterActivity(activities.UpdateKnowledgeActivity) w.RegisterActivity(activities.SearchKnowledgeActivity) w.RegisterActivity(activities.GetContextActivity) w.RegisterActivity(activities.GetVaultActivity) w.RegisterActivity(activities.HealthCheckActivity) w.RegisterActivity(activities.LearnFromExecutionActivity) w.RegisterActivity(activities.DiagnoseIssueActivity) w.RegisterActivity(activities.AnalyzeErrorActivity) w.RegisterActivity(activities.DocumentDecisionActivity) w.RegisterActivity(activities.SearchAndApplyActivity) w.RegisterActivity(activities.RefreshMemoryActivity) } // ActivityOptions memory service activity options type ActivityOptions struct { RetryAttempts int RetryBackoff time.Duration StartTimeout time.Duration HeartbeatRate time.Duration } // DefaultActivityOptions returns sensible defaults func DefaultActivityOptions() *ActivityOptions { return &ActivityOptions{ RetryAttempts: 3, RetryBackoff: time.Second, StartTimeout: 30 * time.Second, HeartbeatRate: 10 * time.Second, } } // ExecuteCreateKnowledge wrapper for CreateKnowledgeActivity func ExecuteCreateKnowledge( ctx workflow.Context, record *KnowledgeRecord, opts *ActivityOptions, ) (string, error) { if opts == nil { opts = DefaultActivityOptions() } activityCtx := workflow.WithActivityOptions(ctx, workflow.ActivityOptions{ ScheduleToCloseTimeout: 2 * time.Minute, StartToCloseTimeout: time.Minute, RetryPolicy: &temporal.RetryPolicy{ InitialInterval: opts.RetryBackoff, BackoffCoefficient: 2.0, MaximumInterval: 30 * time.Second, MaximumAttempts: int32(opts.RetryAttempts), NonRetryableErrorTypes: []string{}, }, }) var result string err := workflow.ExecuteActivity(activityCtx, "CreateKnowledgeActivity", record).Get(activityCtx, &result) return result, err } // ExecuteSearchKnowledge wrapper for SearchKnowledgeActivity func ExecuteSearchKnowledge( ctx workflow.Context, query string, opts *RetrievalOptions, activityOpts *ActivityOptions, ) ([]KnowledgeRecord, error) { if activityOpts == nil { activityOpts = DefaultActivityOptions() } activityCtx := workflow.WithActivityOptions(ctx, workflow.ActivityOptions{ ScheduleToCloseTimeout: 3 * time.Minute, StartToCloseTimeout: 2 * time.Minute, RetryPolicy: &temporal.RetryPolicy{ InitialInterval: activityOpts.RetryBackoff, BackoffCoefficient: 2.0, MaximumInterval: 30 * time.Second, MaximumAttempts: int32(activityOpts.RetryAttempts), }, }) var result []KnowledgeRecord err := workflow.ExecuteActivity(activityCtx, "SearchKnowledgeActivity", query, opts).Get(activityCtx, &result) return result, err } // ExecuteGetContext wrapper for GetContextActivity func ExecuteGetContext( ctx workflow.Context, tool, task string, budget int, opts *ActivityOptions, ) (*ServiceContext, error) { if opts == nil { opts = DefaultActivityOptions() } activityCtx := workflow.WithActivityOptions(ctx, workflow.ActivityOptions{ ScheduleToCloseTimeout: 3 * time.Minute, StartToCloseTimeout: 2 * time.Minute, RetryPolicy: &temporal.RetryPolicy{ InitialInterval: opts.RetryBackoff, BackoffCoefficient: 2.0, MaximumInterval: 30 * time.Second, MaximumAttempts: int32(opts.RetryAttempts), }, }) var result *ServiceContext err := workflow.ExecuteActivity(activityCtx, "GetContextActivity", tool, task, budget).Get(activityCtx, &result) return result, err } // ExecuteDiagnoseIssue wrapper for DiagnoseIssueActivity func ExecuteDiagnoseIssue( ctx workflow.Context, tool, issue string, opts *ActivityOptions, ) ([]string, error) { if opts == nil { opts = DefaultActivityOptions() } activityCtx := workflow.WithActivityOptions(ctx, workflow.ActivityOptions{ ScheduleToCloseTimeout: 2 * time.Minute, StartToCloseTimeout: time.Minute, RetryPolicy: &temporal.RetryPolicy{ InitialInterval: opts.RetryBackoff, BackoffCoefficient: 2.0, MaximumInterval: 30 * time.Second, MaximumAttempts: int32(opts.RetryAttempts), }, }) var result []string err := workflow.ExecuteActivity(activityCtx, "DiagnoseIssueActivity", tool, issue).Get(activityCtx, &result) return result, err } // ExecuteAnalyzeError wrapper for AnalyzeErrorActivity func ExecuteAnalyzeError( ctx workflow.Context, errorMsg string, opts *ActivityOptions, ) ([]KnowledgeRecord, error) { if opts == nil { opts = DefaultActivityOptions() } activityCtx := workflow.WithActivityOptions(ctx, workflow.ActivityOptions{ ScheduleToCloseTimeout: 2 * time.Minute, StartToCloseTimeout: time.Minute, RetryPolicy: &temporal.RetryPolicy{ InitialInterval: opts.RetryBackoff, BackoffCoefficient: 2.0, MaximumInterval: 30 * time.Second, MaximumAttempts: int32(opts.RetryAttempts), }, }) var result []KnowledgeRecord err := workflow.ExecuteActivity(activityCtx, "AnalyzeErrorActivity", errorMsg).Get(activityCtx, &result) return result, err } // ExecuteHealthCheck wrapper for HealthCheckActivity func ExecuteHealthCheck( ctx workflow.Context, opts *ActivityOptions, ) (bool, error) { if opts == nil { opts = DefaultActivityOptions() } activityCtx := workflow.WithActivityOptions(ctx, workflow.ActivityOptions{ ScheduleToCloseTimeout: 1 * time.Minute, StartToCloseTimeout: 30 * time.Second, RetryPolicy: &temporal.RetryPolicy{ InitialInterval: opts.RetryBackoff, BackoffCoefficient: 2.0, MaximumInterval: 15 * time.Second, MaximumAttempts: int32(opts.RetryAttempts), }, }) var result bool err := workflow.ExecuteActivity(activityCtx, "HealthCheckActivity").Get(activityCtx, &result) return result, err } // ExecuteLearnFromExecution wrapper for LearnFromExecutionActivity func ExecuteLearnFromExecution( ctx workflow.Context, taskID, result string, tags []string, opts *ActivityOptions, ) (string, error) { if opts == nil { opts = DefaultActivityOptions() } activityCtx := workflow.WithActivityOptions(ctx, workflow.ActivityOptions{ ScheduleToCloseTimeout: 2 * time.Minute, StartToCloseTimeout: time.Minute, RetryPolicy: &temporal.RetryPolicy{ InitialInterval: opts.RetryBackoff, BackoffCoefficient: 2.0, MaximumInterval: 30 * time.Second, MaximumAttempts: int32(opts.RetryAttempts), }, }) var recordID string err := workflow.ExecuteActivity(activityCtx, "LearnFromExecutionActivity", taskID, result, tags).Get(activityCtx, &recordID) return recordID, err } // ExecuteDocumentDecision wrapper for DocumentDecisionActivity func ExecuteDocumentDecision( ctx workflow.Context, decisionType, decision, reasoning string, opts *ActivityOptions, ) (string, error) { if opts == nil { opts = DefaultActivityOptions() } activityCtx := workflow.WithActivityOptions(ctx, workflow.ActivityOptions{ ScheduleToCloseTimeout: 2 * time.Minute, StartToCloseTimeout: time.Minute, RetryPolicy: &temporal.RetryPolicy{ InitialInterval: opts.RetryBackoff, BackoffCoefficient: 2.0, MaximumInterval: 30 * time.Second, MaximumAttempts: int32(opts.RetryAttempts), }, }) var recordID string err := workflow.ExecuteActivity(activityCtx, "DocumentDecisionActivity", decisionType, decision, reasoning).Get(activityCtx, &recordID) return recordID, err } // ExecuteRefreshMemory wrapper for RefreshMemoryActivity func ExecuteRefreshMemory( ctx workflow.Context, opts *ActivityOptions, ) (map[string]interface{}, error) { if opts == nil { opts = DefaultActivityOptions() } activityCtx := workflow.WithActivityOptions(ctx, workflow.ActivityOptions{ ScheduleToCloseTimeout: 2 * time.Minute, StartToCloseTimeout: time.Minute, RetryPolicy: &temporal.RetryPolicy{ InitialInterval: opts.RetryBackoff, BackoffCoefficient: 2.0, MaximumInterval: 30 * time.Second, MaximumAttempts: int32(opts.RetryAttempts), }, }) var result map[string]interface{} err := workflow.ExecuteActivity(activityCtx, "RefreshMemoryActivity").Get(activityCtx, &result) return result, err } // HeartbeatMemoryActivity sends heartbeat every N seconds // Usage: Long-running memory operations func HeartbeatMemoryActivity(ctx context.Context, maxDuration time.Duration) error { ticker := time.NewTicker(10 * time.Second) defer ticker.Stop() deadline := time.Now().Add(maxDuration) for { select { case <-ticker.C: activity.RecordHeartbeat(ctx, time.Now()) case <-ctx.Done(): return ctx.Err() } if time.Now().After(deadline) { break } } return nil } // MemoryActivityError wraps errors with activity context type MemoryActivityError struct { ActivityName string Attempt int Err error } func (e *MemoryActivityError) Error() string { return fmt.Sprintf("memory activity %s (attempt %d): %v", e.ActivityName, e.Attempt, e.Err) } // CaptureActivityError captures activity execution errors func CaptureActivityError(activityName string, err error) error { if err == nil { return nil } return &MemoryActivityError{ ActivityName: activityName, Attempt: 1, Err: err, } }