20
20
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
21
// THE SOFTWARE.
22
22
23
+ // This file is duplicated in temporalio/temporal/components/nexusoperations/link_converter.go
24
+ // Any changes here or there must be replicated. This is temporary until the
25
+ // temporal repo updates to the most recent SDK version.
26
+
23
27
package nexusoperations
24
28
25
29
import (
26
30
"fmt"
27
31
"net/url"
32
+ "regexp"
28
33
"strconv"
29
- "strings"
30
34
31
35
"github.com/nexus-rpc/sdk-go/nexus"
32
36
commonpb "go.temporal.io/api/common/v1"
33
37
enumspb "go.temporal.io/api/enums/v1"
34
38
)
35
39
36
40
const (
41
+ urlSchemeTemporalKey = "temporal"
42
+ urlPathNamespaceKey = "namespace"
43
+ urlPathWorkflowIDKey = "workflowID"
44
+ urlPathRunIDKey = "runID"
45
+ urlPathTemplate = "/namespaces/%s/workflows/%s/%s/history"
46
+ urlTemplate = "temporal://" + urlPathTemplate
47
+
37
48
linkWorkflowEventReferenceTypeKey = "referenceType"
38
49
linkEventReferenceEventIDKey = "eventID"
39
50
linkEventReferenceEventTypeKey = "eventType"
40
51
)
41
52
42
- func ConvertLinkWorkflowEventToNexusLink (we * commonpb.Link_WorkflowEvent ) (nexus.Link , error ) {
43
- u , err := url .Parse (fmt .Sprintf (
44
- "temporal:///namespaces/%s/workflows/%s/%s/history" ,
45
- url .PathEscape (we .GetNamespace ()),
46
- url .PathEscape (we .GetWorkflowId ()),
47
- url .PathEscape (we .GetRunId ()),
53
+ var (
54
+ rePatternNamespace = fmt .Sprintf (`(?P<%s>[^/]+)` , urlPathNamespaceKey )
55
+ rePatternWorkflowID = fmt .Sprintf (`(?P<%s>[^/]+)` , urlPathWorkflowIDKey )
56
+ rePatternRunID = fmt .Sprintf (`(?P<%s>[^/]+)` , urlPathRunIDKey )
57
+ urlPathRE = regexp .MustCompile (fmt .Sprintf (
58
+ `^/namespaces/%s/workflows/%s/%s/history$` ,
59
+ rePatternNamespace ,
60
+ rePatternWorkflowID ,
61
+ rePatternRunID ,
48
62
))
49
- if err != nil {
50
- return nexus.Link {}, err
63
+ )
64
+
65
+ // ConvertLinkWorkflowEventToNexusLink converts a Link_WorkflowEvent type to Nexus Link.
66
+ func ConvertLinkWorkflowEventToNexusLink (we * commonpb.Link_WorkflowEvent ) nexus.Link {
67
+ u := & url.URL {
68
+ Scheme : urlSchemeTemporalKey ,
69
+ Path : fmt .Sprintf (urlPathTemplate , we .GetNamespace (), we .GetWorkflowId (), we .GetRunId ()),
70
+ RawPath : fmt .Sprintf (
71
+ urlPathTemplate ,
72
+ url .PathEscape (we .GetNamespace ()),
73
+ url .PathEscape (we .GetWorkflowId ()),
74
+ url .PathEscape (we .GetRunId ()),
75
+ ),
51
76
}
52
77
53
78
switch ref := we .GetReference ().(type ) {
@@ -57,9 +82,10 @@ func ConvertLinkWorkflowEventToNexusLink(we *commonpb.Link_WorkflowEvent) (nexus
57
82
return nexus.Link {
58
83
URL : u ,
59
84
Type : string (we .ProtoReflect ().Descriptor ().FullName ()),
60
- }, nil
85
+ }
61
86
}
62
87
88
+ // ConvertNexusLinkToLinkWorkflowEvent converts a Nexus Link to Link_WorkflowEvent.
63
89
func ConvertNexusLinkToLinkWorkflowEvent (link nexus.Link ) (* commonpb.Link_WorkflowEvent , error ) {
64
90
we := & commonpb.Link_WorkflowEvent {}
65
91
if link .Type != string (we .ProtoReflect ().Descriptor ().FullName ()) {
@@ -70,54 +96,76 @@ func ConvertNexusLinkToLinkWorkflowEvent(link nexus.Link) (*commonpb.Link_Workfl
70
96
)
71
97
}
72
98
73
- if link .URL .Scheme != "temporal" {
74
- return nil , fmt .Errorf ("failed to parse link to Link_WorkflowEvent" )
99
+ if link .URL .Scheme != urlSchemeTemporalKey {
100
+ return nil , fmt .Errorf (
101
+ "failed to parse link to Link_WorkflowEvent: invalid scheme: %s" ,
102
+ link .URL .Scheme ,
103
+ )
104
+ }
105
+
106
+ matches := urlPathRE .FindStringSubmatch (link .URL .EscapedPath ())
107
+ if len (matches ) != 4 {
108
+ return nil , fmt .Errorf ("failed to parse link to Link_WorkflowEvent: malformed URL path" )
75
109
}
76
110
77
- pathParts := strings .Split (link .URL .Path , "/" )
78
- if len (pathParts ) != 7 {
79
- return nil , fmt .Errorf ("failed to parse link to Link_WorkflowEvent" )
111
+ var err error
112
+ we .Namespace , err = url .PathUnescape (matches [urlPathRE .SubexpIndex (urlPathNamespaceKey )])
113
+ if err != nil {
114
+ return nil , fmt .Errorf ("failed to parse link to Link_WorkflowEvent: %w" , err )
80
115
}
81
- if pathParts [0 ] != "" || pathParts [1 ] != "namespaces" || pathParts [3 ] != "workflows" || pathParts [6 ] != "history" {
82
- return nil , fmt .Errorf ("failed to parse link to Link_WorkflowEvent" )
116
+
117
+ we .WorkflowId , err = url .PathUnescape (matches [urlPathRE .SubexpIndex (urlPathWorkflowIDKey )])
118
+ if err != nil {
119
+ return nil , fmt .Errorf ("failed to parse link to Link_WorkflowEvent: %w" , err )
83
120
}
84
- we .Namespace = pathParts [2 ]
85
- we .WorkflowId = pathParts [4 ]
86
- we .RunId = pathParts [5 ]
87
- switch link .URL .Query ().Get (linkWorkflowEventReferenceTypeKey ) {
121
+
122
+ we .RunId , err = url .PathUnescape (matches [urlPathRE .SubexpIndex (urlPathRunIDKey )])
123
+ if err != nil {
124
+ return nil , fmt .Errorf ("failed to parse link to Link_WorkflowEvent: %w" , err )
125
+ }
126
+
127
+ switch refType := link .URL .Query ().Get (linkWorkflowEventReferenceTypeKey ); refType {
88
128
case string ((& commonpb.Link_WorkflowEvent_EventReference {}).ProtoReflect ().Descriptor ().Name ()):
89
129
eventRef , err := convertURLQueryToLinkWorkflowEventEventReference (link .URL .Query ())
90
130
if err != nil {
91
- return nil , err
131
+ return nil , fmt . Errorf ( "failed to parse link to Link_WorkflowEvent: %w" , err )
92
132
}
93
133
we .Reference = & commonpb.Link_WorkflowEvent_EventRef {
94
134
EventRef : eventRef ,
95
135
}
136
+ default :
137
+ return nil , fmt .Errorf (
138
+ "failed to parse link to Link_WorkflowEvent: unknown reference type: %q" ,
139
+ refType ,
140
+ )
96
141
}
97
142
98
143
return we , nil
99
144
}
100
145
101
146
func convertLinkWorkflowEventEventReferenceToURLQuery (eventRef * commonpb.Link_WorkflowEvent_EventReference ) string {
102
- values := url.Values {
103
- linkWorkflowEventReferenceTypeKey : [] string { string (eventRef .ProtoReflect ().Descriptor ().Name ())},
104
- linkEventReferenceEventIDKey : [] string { strconv . FormatInt ( eventRef .GetEventId (), 10 )},
105
- linkEventReferenceEventTypeKey : [] string { eventRef . GetEventType (). String ()},
147
+ values := url.Values {}
148
+ values . Set ( linkWorkflowEventReferenceTypeKey , string (eventRef .ProtoReflect ().Descriptor ().Name ()))
149
+ if eventRef .GetEventId () > 0 {
150
+ values . Set ( linkEventReferenceEventIDKey , strconv . FormatInt ( eventRef . GetEventId (), 10 ))
106
151
}
152
+ values .Set (linkEventReferenceEventTypeKey , eventRef .GetEventType ().String ())
107
153
return values .Encode ()
108
154
}
109
155
110
156
func convertURLQueryToLinkWorkflowEventEventReference (queryValues url.Values ) (* commonpb.Link_WorkflowEvent_EventReference , error ) {
111
- eventID , err := strconv .ParseInt (queryValues .Get (linkEventReferenceEventIDKey ), 10 , 64 )
112
- if err != nil {
113
- return nil , err
157
+ var err error
158
+ eventRef := & commonpb.Link_WorkflowEvent_EventReference {}
159
+ eventIDValue := queryValues .Get (linkEventReferenceEventIDKey )
160
+ if eventIDValue != "" {
161
+ eventRef .EventId , err = strconv .ParseInt (queryValues .Get (linkEventReferenceEventIDKey ), 10 , 64 )
162
+ if err != nil {
163
+ return nil , err
164
+ }
114
165
}
115
- eventType , err : = enumspb .EventTypeFromString (queryValues .Get (linkEventReferenceEventTypeKey ))
166
+ eventRef . EventType , err = enumspb .EventTypeFromString (queryValues .Get (linkEventReferenceEventTypeKey ))
116
167
if err != nil {
117
168
return nil , err
118
169
}
119
- return & commonpb.Link_WorkflowEvent_EventReference {
120
- EventId : eventID ,
121
- EventType : eventType ,
122
- }, nil
170
+ return eventRef , nil
123
171
}
0 commit comments