@@ -13,26 +13,42 @@ package dex
1313import "github.com/superdurable/dex/sdk-go/gen/dexpb"
1414
1515// Attribute defines a typed persisted value.
16+ //
17+ // Declare an Attribute once, include it in the Flow's PersistenceSchema, and reuse the same value
18+ // from Step and RPC code. Values use the SDK's native scalar and JSON encoding rules.
1619// String values require valid UTF-8; use []byte for arbitrary bytes.
20+ //
21+ // Example:
22+ //
23+ // var orderStatus = dex.DefineAttribute[string](
24+ // "order-status",
25+ // dex.Indexed(dex.AttributeIndex{Type: dex.IndexKeyword}),
26+ // )
1727type Attribute [T any ] struct {
1828 name string
1929 index * AttributeIndex
2030}
2131
32+ // DefineAttribute creates a typed Attribute with a stable name and optional search index.
33+ // The definition does not perform I/O; register it through PersistenceSchema before use.
2234func DefineAttribute [T any ](key string , options ... AttributeOption ) Attribute [T ] {
2335 config := applyAttributeOptions (options )
2436 return Attribute [T ]{name : key , index : config .index }
2537}
2638
2739// AttributeDef is the interface of Attribute, without Go's generic
2840// So that internal sdk can use it to workaround Go's generic limitations
41+ //
42+ // AttributeDef is internal to the SDK. Applications create values with DefineAttribute or
43+ // DefineAttributeMap, then pass them to PersistenceSchema and Client methods.
2944type AttributeDef interface {
3045 attributeName () string
3146 attributeIndex () * AttributeIndex
3247 attributeIsMap () bool
3348}
3449
3550// Get returns the current value. Missing values return AttributeNotFoundError.
51+ // It returns an error when ctx is not an SDK invocation or the value cannot be decoded.
3652func (a Attribute [T ]) Get (ctx Context ) (value T , err error ) {
3753 invocation , ok := ctx .(attributeInvocation )
3854 if ! ok {
@@ -48,6 +64,8 @@ func (a Attribute[T]) Get(ctx Context) (value T, err error) {
4864 return value , nil
4965}
5066
67+ // Set stages value for durable persistence when the current Step or RPC invocation succeeds.
68+ // It returns an error when ctx is not an SDK invocation or value cannot be encoded or indexed.
5169func (a Attribute [T ]) Set (ctx Context , value T ) error {
5270 invocation , ok := ctx .(attributeInvocation )
5371 if ! ok {
@@ -56,6 +74,8 @@ func (a Attribute[T]) Set(ctx Context, value T) error {
5674 return invocation .setAttribute (a .name , value , a .index )
5775}
5876
77+ // Delete stages removal of this Attribute. Deleting a missing value is valid.
78+ // It returns an error when ctx is not an SDK invocation.
5979func (a Attribute [T ]) Delete (ctx Context ) error {
6080 invocation , ok := ctx .(attributeInvocation )
6181 if ! ok {
@@ -64,6 +84,7 @@ func (a Attribute[T]) Delete(ctx Context) error {
6484 return invocation .deleteAttribute (a .name , a .index )
6585}
6686
87+ // AttributeName returns the stable name sent to Dex and used in PersistenceSchema.
6788func (a Attribute [T ]) AttributeName () string {
6889 return a .name
6990}
@@ -81,18 +102,24 @@ func (Attribute[T]) attributeIsMap() bool {
81102}
82103
83104// AttributeMap defines keyed typed persisted values.
105+ //
106+ // Register the map once in PersistenceSchema, then supply an instance string for every access and
107+ // lock.
84108// String values require valid UTF-8; use []byte for arbitrary bytes.
85109type AttributeMap [T any ] struct {
86110 name string
87111 index * AttributeIndex
88112}
89113
114+ // DefineAttributeMap creates a typed Attribute map with a stable name and optional search index.
115+ // The definition performs no I/O; register it through PersistenceSchema before use.
90116func DefineAttributeMap [T any ](name string , options ... AttributeOption ) AttributeMap [T ] {
91117 config := applyAttributeOptions (options )
92118 return AttributeMap [T ]{name : name , index : config .index }
93119}
94120
95121// Get returns the current map value. Missing instances return AttributeNotFoundError.
122+ // It returns an error when ctx is invalid or the value cannot be decoded.
96123func (a AttributeMap [T ]) Get (
97124 ctx Context ,
98125 instance string ,
@@ -114,6 +141,8 @@ func (a AttributeMap[T]) Get(
114141 return value , nil
115142}
116143
144+ // Set stages value for one map instance when the invocation succeeds.
145+ // It returns an error for an invalid context or a value that cannot be encoded or indexed.
117146func (a AttributeMap [T ]) Set (ctx Context , instance string , value T ) error {
118147 invocation , ok := ctx .(attributeInvocation )
119148 if ! ok {
@@ -122,6 +151,8 @@ func (a AttributeMap[T]) Set(ctx Context, instance string, value T) error {
122151 return invocation .setAttributeMap (a .name , instance , value , a .index )
123152}
124153
154+ // Delete stages removal of one map instance. Deleting a missing instance is valid.
155+ // It returns an error when ctx is not an SDK invocation.
125156func (a AttributeMap [T ]) Delete (ctx Context , instance string ) error {
126157 invocation , ok := ctx .(attributeInvocation )
127158 if ! ok {
@@ -130,6 +161,7 @@ func (a AttributeMap[T]) Delete(ctx Context, instance string) error {
130161 return invocation .deleteAttributeMap (a .name , instance , a .index )
131162}
132163
164+ // AttributeName returns the stable shared name of this Attribute map.
133165func (a AttributeMap [T ]) AttributeName () string {
134166 return a .name
135167}
@@ -146,47 +178,68 @@ func (AttributeMap[T]) attributeIsMap() bool {
146178 return true
147179}
148180
181+ // AttributeOption configures an Attribute or AttributeMap definition.
182+ // Use Indexed to create values; custom implementations are not supported.
149183type AttributeOption interface {
150184 applyAttribute (* attributeConfig )
151185}
152186
187+ // IndexType identifies the search representation required for an indexed Attribute value.
153188type IndexType uint8
154189
155190const (
191+ // IndexKeyword indexes one exact UTF-8 string for equality and aggregation queries.
156192 IndexKeyword IndexType = iota + 1
193+ // IndexFullText indexes analyzed UTF-8 text for full-text queries.
157194 IndexFullText
195+ // IndexKeywordArray indexes a slice or array of exact UTF-8 strings.
158196 IndexKeywordArray
197+ // IndexInt indexes a signed or unsigned integer that fits in int64.
159198 IndexInt
199+ // IndexDouble indexes a finite floating-point value.
160200 IndexDouble
201+ // IndexBool indexes a Boolean value.
161202 IndexBool
203+ // IndexDatetime indexes time.Time or an RFC3339Nano string.
162204 IndexDatetime
163205)
164206
165207// AttributeIndex configures visibility indexing; datetime values use time.Time or RFC3339Nano strings.
208+ // An empty IndexKey uses the Attribute name
209+ // for single values and a derived physical name for map instances.
166210type AttributeIndex struct {
167- Type IndexType
211+ // Type selects the required value representation.
212+ Type IndexType
213+ // IndexKey overrides the physical search field; empty uses the Attribute-derived key.
168214 IndexKey string
169215}
170216
217+ // Indexed enables search indexing with index on an Attribute or AttributeMap definition.
171218func Indexed (index AttributeIndex ) AttributeOption {
172219 return indexedAttributeOption {index : index }
173220}
174221
222+ // AttributeLock identifies one Attribute or Attribute-map instance lock.
223+ // Create locks with LockAttribute or LockAttributeMap, then place them in StepOptions or InvokeOptions.
175224type AttributeLock interface {
176225 attributeLock ()
177226}
178227
228+ // LockAttribute creates a lock for the single value represented by attribute.
179229func LockAttribute [T any ](attribute Attribute [T ]) AttributeLock {
180230 return attributeLock {name : attribute .name }
181231}
182232
233+ // LockAttributeMap creates a lock scoped to one Attribute-map instance.
183234func LockAttributeMap [T any ](
184235 attribute AttributeMap [T ],
185236 instance string ,
186237) AttributeLock {
187238 return attributeLock {name : attribute .name , instance : instance , isMap : true }
188239}
189240
241+ // InitialAttribute encodes a value for StartFlowOptions.Attributes.
242+ // It returns ValueMappingError when the value is unsupported or incompatible with its index.
190243func InitialAttribute [T any ](
191244 attribute Attribute [T ],
192245 value T ,
@@ -204,10 +257,14 @@ func InitialAttribute[T any](
204257 }, nil
205258}
206259
260+ // InitialAttributeDef is an encoded Attribute initialization accepted by StartFlowOptions.
261+ // Values are created by InitialAttribute and InitialAttributeMapValue.
207262type InitialAttributeDef interface {
208263 initialAttribute ()
209264}
210265
266+ // InitialAttributeMapValue encodes one Attribute-map instance for StartFlowOptions.Attributes.
267+ // It returns ValueMappingError when the value is unsupported or incompatible with its index.
211268func InitialAttributeMapValue [T any ](
212269 attribute AttributeMap [T ],
213270 instance string ,
0 commit comments