Skip to content
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion internal/cmd/tools/doclink/doclink.go
Original file line number Diff line number Diff line change
Expand Up @@ -577,7 +577,7 @@ func isValidDefinitionWithMatch(line, private string, inGroup string, insideStru
if inGroup == "const" || inGroup == "var" {
return tokens[0] == private
} else if inGroup == "type" {
return len(tokens) > 2 && tokens[2] == private
return len(tokens) > 1 && (tokens[0] == private || len(tokens) > 2 && tokens[2] == private)
Comment thread
cursor[bot] marked this conversation as resolved.
}

// Handle single-line struct, variable, or function definitions
Expand Down
83 changes: 83 additions & 0 deletions internal/cmd/tools/doclink/doclink_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package main

import (
"os"
"path/filepath"
"strings"
"testing"
)

func TestIsValidDefinitionWithMatchGroupedInterface(t *testing.T) {
t.Parallel()

if !isValidDefinitionWithMatch("ContextPropagator interface {", "ContextPropagator", "type", false) {
t.Fatal("expected grouped interface declaration to match exposed internal type")
}
}

func TestIsValidDefinitionWithMatchGroupedNamedType(t *testing.T) {
t.Parallel()

if !isValidDefinitionWithMatch("SessionState int", "SessionState", "type", false) {
t.Fatal("expected grouped named type declaration to match exposed internal type")
}
}

func TestIsValidDefinitionWithMatchSkipsEmbeddedInterfaceMember(t *testing.T) {
t.Parallel()

if isValidDefinitionWithMatch("SendChannel", "SendChannel", "type", false) {
t.Fatal("expected embedded interface member not to match exposed internal type")
}
}

func TestProcessInternalAddsDocLinkForGroupedInterface(t *testing.T) {
oldChangesNeeded := changesNeeded
changesNeeded = false
t.Cleanup(func() {
changesNeeded = oldChangesNeeded
})

dir := t.TempDir()
path := filepath.Join(dir, "headers.go")
source := `package internal

type (
// ContextPropagator is an interface that determines what information from
// context to pass along.
ContextPropagator interface {
Inject() error
}
)
`
if err := os.WriteFile(path, []byte(source), 0644); err != nil {
t.Fatal(err)
}

file, err := os.Open(path)
if err != nil {
t.Fatal(err)
}

pairs := map[string]map[string]string{
"workflow": {
"ContextPropagator": "ContextPropagator",
},
}
if err := processInternal(config{fix: true}, file, pairs); err != nil {
t.Fatal(err)
}
if err := file.Close(); err != nil {
t.Fatal(err)
}

updatedBytes, err := os.ReadFile(path)
if err != nil {
t.Fatal(err)
}
updated := string(updatedBytes)
want := "// Exposed as: [go.temporal.io/sdk/workflow.ContextPropagator]"
if !strings.Contains(updated, want) {
t.Fatalf("expected generated doc link %q in:\n%s", want, updated)
}
}
4 changes: 4 additions & 0 deletions internal/deployment_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,8 @@ type (
// DeploymentListIterator is an iterator for deployments.
//
// NOTE: Experimental
//
// Exposed as: [go.temporal.io/sdk/client.DeploymentListIterator]
DeploymentListIterator interface {
// HasNext - Return whether this iterator has next value.
HasNext() bool
Expand Down Expand Up @@ -269,6 +271,8 @@ type (
// DeploymentClient is the client that manages deployments.
//
// NOTE: Experimental
//
// Exposed as: [go.temporal.io/sdk/client.DeploymentClient]
DeploymentClient interface {
// Describes an existing deployment.
//
Expand Down
6 changes: 6 additions & 0 deletions internal/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,8 @@ type (
}

// UnknownExternalWorkflowExecutionError can be returned when external workflow doesn't exist
//
// Exposed as: [go.temporal.io/sdk/temporal.UnknownExternalWorkflowExecutionError]
UnknownExternalWorkflowExecutionError struct{}

// ServerError can be returned from server.
Expand Down Expand Up @@ -322,9 +324,13 @@ type (
// ChildWorkflowExecutionAlreadyStartedError is set as the cause of
// ChildWorkflowExecutionError when failure is due the child workflow having
// already started.
//
// Exposed as: [go.temporal.io/sdk/temporal.ChildWorkflowExecutionAlreadyStartedError]
ChildWorkflowExecutionAlreadyStartedError struct{}

// NamespaceNotFoundError is set as the cause when failure is due namespace not found.
//
// Exposed as: [go.temporal.io/sdk/temporal.NamespaceNotFoundError]
NamespaceNotFoundError struct{}

// WorkflowExecutionError is returned from workflow.
Expand Down
8 changes: 8 additions & 0 deletions internal/headers.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,24 @@ import (

// HeaderWriter is an interface to write information to temporal headers
type (
//
// Exposed as: [go.temporal.io/sdk/workflow.HeaderWriter]
HeaderWriter interface {
Set(string, *commonpb.Payload)
}

// HeaderReader is an interface to read information from temporal headers
//
// Exposed as: [go.temporal.io/sdk/workflow.HeaderReader]
HeaderReader interface {
Get(string) (*commonpb.Payload, bool)
ForEachKey(handler func(string, *commonpb.Payload) error) error
}

// ContextPropagator is an interface that determines what information from
// context to pass along
//
// Exposed as: [go.temporal.io/sdk/workflow.ContextPropagator]
ContextPropagator interface {
// Inject injects information from a Go Context into headers
Inject(context.Context, HeaderWriter) error
Expand All @@ -45,6 +51,8 @@ type (
// Note that data converters may be called in non-context-aware situations to
// convert payloads that may not be customized per context. Data converter
// implementers should not expect or require contextual data be present.
//
// Exposed as: [go.temporal.io/sdk/workflow.ContextAware]
ContextAware interface {
WithWorkflowContext(ctx Context) converter.DataConverter
WithContext(ctx context.Context) converter.DataConverter
Expand Down
8 changes: 8 additions & 0 deletions internal/schedule_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,8 @@ type (
}

// ScheduleAction represents an action a schedule can take.
//
// Exposed as: [go.temporal.io/sdk/client.ScheduleAction]
ScheduleAction interface {
isScheduleAction()
}
Expand Down Expand Up @@ -597,6 +599,8 @@ type (
}

// ScheduleHandle represents a created schedule.
//
// Exposed as: [go.temporal.io/sdk/client.ScheduleHandle]
ScheduleHandle interface {
// GetID returns the schedule ID associated with this handle.
GetID() string
Expand Down Expand Up @@ -700,6 +704,8 @@ type (

// ScheduleListIterator represents the interface for
// schedule iterator
//
// Exposed as: [go.temporal.io/sdk/client.ScheduleListIterator]
ScheduleListIterator interface {
// HasNext return whether this iterator has next value
HasNext() bool
Expand All @@ -709,6 +715,8 @@ type (
}

// Client for creating Schedules and creating Schedule handles
//
// Exposed as: [go.temporal.io/sdk/client.ScheduleClient]
ScheduleClient interface {
// Create a new Schedule.
Create(ctx context.Context, options ScheduleOptions) (ScheduleHandle, error)
Expand Down
4 changes: 3 additions & 1 deletion internal/session.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ type (
Taskqueue string
}

//
// Exposed as: [go.temporal.io/sdk/workflow.SessionState]
SessionState int

sessionTokenBucket struct {
Expand All @@ -77,7 +79,7 @@ type (
*sync.Mutex
// doneChanMap is keyed by sessionID. CreateSession creates and stores each
// channel, and CompleteSession deletes and closes it to signal session end.
doneChanMap map[string]chan struct{}
doneChanMap map[string]chan struct{}
resourceID string
resourceSpecificTaskqueue string
sessionTokenBucket *sessionTokenBucket
Expand Down
24 changes: 24 additions & 0 deletions internal/workflow.go
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,8 @@ var (

type (
// SendChannel is a write only view of the Channel
//
// Exposed as: [go.temporal.io/sdk/workflow.SendChannel]
SendChannel interface {
// Name returns the name of the Channel.
// If the Channel was retrieved from a GetSignalChannel call, Name returns the signal name.
Expand All @@ -197,6 +199,8 @@ type (
}

// ReceiveChannel is a read only view of the Channel
//
// Exposed as: [go.temporal.io/sdk/workflow.ReceiveChannel]
ReceiveChannel interface {
// Name returns the name of the Channel.
// If the Channel was retrieved from a GetSignalChannel call, Name returns the signal name.
Expand Down Expand Up @@ -252,13 +256,17 @@ type (

// Channel must be used by workflow code instead of native go channels.
// Use workflow.NewChannel(ctx) method to create Channel instance.
//
// Exposed as: [go.temporal.io/sdk/workflow.Channel]
Channel interface {
SendChannel
ReceiveChannel
}

// Selector must be used by workflow code instead of native go select.
// Use workflow.NewSelector(ctx) to create a selector.
//
// Exposed as: [go.temporal.io/sdk/workflow.Selector]
Selector interface {
// AddReceive registers a callback function to be called when a channel has a message to receive.
// The callback is called when Select(ctx) is called.
Expand Down Expand Up @@ -290,6 +298,8 @@ type (
// WaitGroup must be used instead of native go sync.WaitGroup by
// workflow code. Use workflow.NewWaitGroup(ctx) method to create
// a new WaitGroup instance
//
// Exposed as: [go.temporal.io/sdk/workflow.WaitGroup]
WaitGroup interface {
// Add adds delta, which may be negative, to the WaitGroup task counter.
// If the counter becomes zero, all goroutines blocked on WaitGroup.Wait are released.
Expand All @@ -313,6 +323,8 @@ type (
// Mutex must be used instead of native go sync.Mutex by
// workflow code. Use workflow.NewMutex(ctx) method to create
// a new Mutex instance
//
// Exposed as: [go.temporal.io/sdk/workflow.Mutex]
Mutex interface {
// Lock blocks until the mutex is acquired.
// Returns CanceledError if the ctx is canceled.
Expand All @@ -330,6 +342,8 @@ type (
// Semaphore must be used instead of semaphore.Weighted by
// workflow code. Use workflow.NewSemaphore(ctx) method to create
// a new Semaphore instance
//
// Exposed as: [go.temporal.io/sdk/workflow.Semaphore]
Semaphore interface {
// Acquire acquires the semaphore with a weight of n.
// On success, returns nil. On failure, returns CanceledError and leaves the semaphore unchanged.
Expand All @@ -342,6 +356,8 @@ type (
}

// Future represents the result of an asynchronous computation.
//
// Exposed as: [go.temporal.io/sdk/workflow.Future]
Future interface {
// Get blocks until the future is ready. When ready it either returns non nil error or assigns result value to
// the provided pointer.
Expand All @@ -366,6 +382,8 @@ type (

// Settable is used to set value or error on a future.
// See more: workflow.NewFuture(ctx).
//
// Exposed as: [go.temporal.io/sdk/workflow.Settable]
Settable interface {
Set(value interface{}, err error)
SetValue(value interface{})
Expand All @@ -374,6 +392,8 @@ type (
}

// ChildWorkflowFuture represents the result of a child workflow execution
//
// Exposed as: [go.temporal.io/sdk/workflow.ChildWorkflowFuture]
ChildWorkflowFuture interface {
Future
// GetChildWorkflowExecution returns a future that will be ready when child workflow execution started. You can
Expand Down Expand Up @@ -414,6 +434,8 @@ type (
dataConverter converter.DataConverter
}
// Version represents a change version. See GetVersion call.
//
// Exposed as: [go.temporal.io/sdk/workflow.Version]
Version int

// ChildWorkflowOptions stores all child workflow specific parameters that will be stored inside of a Context.
Expand Down Expand Up @@ -587,6 +609,8 @@ type (
}

// DynamicRegisterActivityOptions consists of options for registering a dynamic activity
//
// Exposed as: [go.temporal.io/sdk/activity.DynamicRegisterOptions]
DynamicRegisterActivityOptions struct{}

// DynamicRuntimeWorkflowOptions are options for a dynamic workflow.
Expand Down
Loading