Skip to content

Commit

Permalink
fix: remove once in ftl.Map to allow changing underlying values (#1435)
Browse files Browse the repository at this point in the history
fixes #1390

`ftl.Map` was just using `once` as an optimisation.
But this unit test case was not being handled properly:
```
ctx := ftltest.Context(
    ftltest.WithConfig(example, "hello"),
)

//Call a verb that uses ftl.Map with example config
resp, err := Verb(ctx, req)

ctx = ftltest.Context(
    ftltest.WithConfig(example, "world"),
)

//When this execution of the verb is done, it should execute again because the underlying value is different (hello -> world)
resp, err = Verb(ctx, req)
```
To solve this, now the mapping func is called each time.

For use cases where modules want to map a `*sql.DB` to a `DAL`, it will
create a new DAL instance each time
  • Loading branch information
matt2e authored May 8, 2024
1 parent 5b3f7c3 commit acdb53a
Show file tree
Hide file tree
Showing 2 changed files with 7 additions and 28 deletions.
20 changes: 7 additions & 13 deletions go-runtime/ftl/map.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,22 @@ package ftl

import (
"context"
"sync"
)

type MapHandle[T, U any] struct {
fn func(context.Context, T) (U, error)
getter Handle[T]
out U
once *sync.Once
}

func (sh *MapHandle[T, U]) Get(ctx context.Context) U {
sh.once.Do(func() {
t, err := sh.fn(ctx, sh.getter.Get(ctx))
if err != nil {
panic(err)
}
sh.out = t
})
return sh.out
func (mh *MapHandle[T, U]) Get(ctx context.Context) U {
t, err := mh.fn(ctx, mh.getter.Get(ctx))
if err != nil {
panic(err)
}
return t
}

// Map an FTL resource type to a new type.
func Map[T, U any](getter Handle[T], fn func(context.Context, T) (U, error)) MapHandle[T, U] {
return MapHandle[T, U]{fn: fn, getter: getter, once: &sync.Once{}}
return MapHandle[T, U]{fn: fn, getter: getter}
}
15 changes: 0 additions & 15 deletions go-runtime/ftl/map_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,6 @@ type intHandle int

func (s intHandle) Get(ctx context.Context) int { return int(s) }

func TestMapBaseCase(t *testing.T) {
incrementer := 0

h := intHandle(123)
ctx := context.Background()
once := Map(h, func(ctx context.Context, n int) (string, error) {
incrementer++
return fmt.Sprintf("handle: %d", n), nil
})

assert.Equal(t, once.Get(ctx), "handle: 123")
assert.Equal(t, once.Get(ctx), "handle: 123")
assert.Equal(t, incrementer, 1)
}

func TestMapPanic(t *testing.T) {
ctx := context.Background()
n := intHandle(1)
Expand Down

0 comments on commit acdb53a

Please sign in to comment.