1
0
mirror of https://github.com/IBM/fp-go.git synced 2025-08-10 22:31:32 +02:00

fix: add WithLock to limit concurrency

Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>
This commit is contained in:
Dr. Carsten Leue
2023-10-22 21:07:40 +02:00
parent 6a4cdfa891
commit 9da484b79e
23 changed files with 604 additions and 6 deletions

View File

@@ -0,0 +1,37 @@
// Copyright (c) 2023 IBM Corp.
// All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package readerioeither
import (
G "github.com/IBM/fp-go/context/readerioeither/generic"
E "github.com/IBM/fp-go/either"
)
// Bracket makes sure that a resource is cleaned up in the event of an error. The release action is called regardless of
// whether the body action returns and error or not.
func Bracket[
A, B, ANY any](
acquire ReaderIOEither[A],
use func(A) ReaderIOEither[B],
release func(A, E.Either[error, B]) ReaderIOEither[ANY],
) ReaderIOEither[B] {
return G.Bracket[ReaderIOEither[A], ReaderIOEither[B], ReaderIOEither[ANY]](
acquire,
use,
release,
)
}

View File

@@ -0,0 +1,53 @@
// Copyright (c) 2023 IBM Corp.
// All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package generic
import (
"context"
E "github.com/IBM/fp-go/either"
G "github.com/IBM/fp-go/internal/bracket"
I "github.com/IBM/fp-go/readerio/generic"
)
// Bracket makes sure that a resource is cleaned up in the event of an error. The release action is called regardless of
// whether the body action returns and error or not.
func Bracket[
GA ~func(context.Context) TA,
GB ~func(context.Context) TB,
GANY ~func(context.Context) TANY,
TA ~func() E.Either[error, A],
TB ~func() E.Either[error, B],
TANY ~func() E.Either[error, ANY],
A, B, ANY any](
acquire GA,
use func(A) GB,
release func(A, E.Either[error, B]) GANY,
) GB {
return G.Bracket[GA, GB, GANY, E.Either[error, B], A, B](
I.Of[GB, TB, context.Context, E.Either[error, B]],
MonadChain[GA, GB, TA, TB, A, B],
I.MonadChain[GB, GB, TB, TB, context.Context, E.Either[error, B], E.Either[error, B]],
MonadChain[GANY, GB, TANY, TB, ANY, B],
acquire,
use,
release,
)
}

View File

@@ -432,10 +432,10 @@ func FromIOEither[
func FromIO[
GRA ~func(context.Context) GIOA,
GIOA ~func() E.Either[error, A],
GIOB ~func() A,
GIOA ~func() E.Either[error, A],
A any](t GIOB) GRA {
return RIE.FromIO[GRA](t)
}
@@ -571,7 +571,7 @@ func Timer[
](delay time.Duration) GRA {
return F.Pipe2(
IO.Now[func() time.Time](),
FromIO[GRA, GIOA, func() time.Time],
FromIO[GRA, func() time.Time],
Delay[GRA](delay),
)
}

View File

@@ -0,0 +1,44 @@
// Copyright (c) 2023 IBM Corp.
// All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package generic
import (
"context"
E "github.com/IBM/fp-go/either"
F "github.com/IBM/fp-go/function"
IO "github.com/IBM/fp-go/io/generic"
)
// WithLock executes the provided IO operation in the scope of a lock
func WithLock[
GRA ~func(context.Context) GIOA,
GIOA ~func() E.Either[error, A],
GRCANCEL ~func(context.Context) GIOCANCEL,
GIOCANCEL ~func() E.Either[error, context.CancelFunc],
A any](lock GRCANCEL) func(fa GRA) GRA {
type GRANY func(ctx context.Context) func() E.Either[error, any]
type IOANY func() any
return F.Flow2(
F.Constant1[context.CancelFunc, GRA],
WithResource[GRA, GRCANCEL, GRANY](lock, F.Flow2(
IO.FromImpure[IOANY, context.CancelFunc],
FromIO[GRANY, IOANY],
)),
)
}

View File

@@ -0,0 +1,27 @@
// Copyright (c) 2023 IBM Corp.
// All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package readerioeither
import (
"context"
G "github.com/IBM/fp-go/context/readerioeither/generic"
)
// WithLock executes the provided IO operation in the scope of a lock
func WithLock[A any](lock ReaderIOEither[context.CancelFunc]) func(fa ReaderIOEither[A]) ReaderIOEither[A] {
return G.WithLock[ReaderIOEither[A]](lock)
}

30
io/bracket.go Normal file
View File

@@ -0,0 +1,30 @@
// Copyright (c) 2023 IBM Corp.
// All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package io
import (
G "github.com/IBM/fp-go/io/generic"
)
// Bracket makes sure that a resource is cleaned up in the event of an error. The release action is called regardless of
// whether the body action returns and error or not.
func Bracket[A, B, ANY any](
acquire IO[A],
use func(A) IO[B],
release func(A, B) IO[ANY],
) IO[B] {
return G.Bracket(acquire, use, release)
}

44
io/generic/bracket.go Normal file
View File

@@ -0,0 +1,44 @@
// Copyright (c) 2023 IBM Corp.
// All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package generic
import (
G "github.com/IBM/fp-go/internal/bracket"
)
// Bracket makes sure that a resource is cleaned up in the event of an error. The release action is called regardless of
// whether the body action returns and error or not.
func Bracket[
GA ~func() A,
GB ~func() B,
GANY ~func() ANY,
A, B, ANY any](
acquire GA,
use func(A) GB,
release func(A, B) GANY,
) GB {
return G.Bracket[GA, GB, GANY, B, A, B](
Of[GB, B],
MonadChain[GA, GB, A, B],
MonadChain[GB, GB, B, B],
MonadChain[GANY, GB, ANY, B],
acquire,
use,
release,
)
}

30
io/generic/sync.go Normal file
View File

@@ -0,0 +1,30 @@
// Copyright (c) 2023 IBM Corp.
// All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package generic
import (
"context"
)
// WithLock executes the provided IO operation in the scope of a lock
func WithLock[GA ~func() A, A any](lock func() context.CancelFunc) func(fa GA) GA {
return func(fa GA) GA {
return func() A {
defer lock()()
return fa()
}
}
}

28
io/sync.go Normal file
View File

@@ -0,0 +1,28 @@
// Copyright (c) 2023 IBM Corp.
// All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package io
import (
"context"
G "github.com/IBM/fp-go/io/generic"
L "github.com/IBM/fp-go/lazy"
)
// WithLock executes the provided [IO] operation in the scope of a lock
func WithLock[A any](lock L.Lazy[context.CancelFunc]) func(fa IO[A]) IO[A] {
return G.WithLock[IO[A]](lock)
}

View File

@@ -17,7 +17,7 @@ package generic
import (
ET "github.com/IBM/fp-go/either"
G "github.com/IBM/fp-go/internal/file"
G "github.com/IBM/fp-go/internal/bracket"
I "github.com/IBM/fp-go/io/generic"
)

28
ioeither/generic/sync.go Normal file
View File

@@ -0,0 +1,28 @@
// Copyright (c) 2023 IBM Corp.
// All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package generic
import (
"context"
ET "github.com/IBM/fp-go/either"
G "github.com/IBM/fp-go/io/generic"
)
// WithLock executes the provided IO operation in the scope of a lock
func WithLock[GA ~func() ET.Either[E, A], E, A any](lock func() context.CancelFunc) func(fa GA) GA {
return G.WithLock[GA](lock)
}

28
ioeither/sync.go Normal file
View File

@@ -0,0 +1,28 @@
// Copyright (c) 2023 IBM Corp.
// All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package ioeither
import (
"context"
G "github.com/IBM/fp-go/ioeither/generic"
L "github.com/IBM/fp-go/lazy"
)
// WithLock executes the provided IO operation in the scope of a lock
func WithLock[E, A any](lock L.Lazy[context.CancelFunc]) func(fa IOEither[E, A]) IOEither[E, A] {
return G.WithLock[IOEither[E, A]](lock)
}

31
iooption/bracket.go Normal file
View File

@@ -0,0 +1,31 @@
// Copyright (c) 2023 IBM Corp.
// All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package iooption
import (
G "github.com/IBM/fp-go/iooption/generic"
O "github.com/IBM/fp-go/option"
)
// Bracket makes sure that a resource is cleaned up in the event of an error. The release action is called regardless of
// whether the body action returns and error or not.
func Bracket[E, A, B, ANY any](
acquire IOOption[A],
use func(A) IOOption[B],
release func(A, O.Option[B]) IOOption[ANY],
) IOOption[B] {
return G.Bracket(acquire, use, release)
}

View File

@@ -0,0 +1,46 @@
// Copyright (c) 2023 IBM Corp.
// All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package generic
import (
G "github.com/IBM/fp-go/internal/bracket"
I "github.com/IBM/fp-go/io/generic"
O "github.com/IBM/fp-go/option"
)
// Bracket makes sure that a resource is cleaned up in the event of an error. The release action is called regardless of
// whether the body action returns and error or not.
func Bracket[
GA ~func() O.Option[A],
GB ~func() O.Option[B],
GANY ~func() O.Option[ANY],
A, B, ANY any](
acquire GA,
use func(A) GB,
release func(A, O.Option[B]) GANY,
) GB {
return G.Bracket[GA, GB, GANY, O.Option[B], A, B](
I.Of[GB, O.Option[B]],
MonadChain[GA, GB, A, B],
I.MonadChain[GB, GB, O.Option[B], O.Option[B]],
MonadChain[GANY, GB, ANY, B],
acquire,
use,
release,
)
}

28
iooption/generic/sync.go Normal file
View File

@@ -0,0 +1,28 @@
// Copyright (c) 2023 IBM Corp.
// All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package generic
import (
"context"
G "github.com/IBM/fp-go/io/generic"
O "github.com/IBM/fp-go/option"
)
// WithLock executes the provided IO operation in the scope of a lock
func WithLock[GA ~func() O.Option[A], A any](lock func() context.CancelFunc) func(fa GA) GA {
return G.WithLock[GA](lock)
}

28
iooption/sync.go Normal file
View File

@@ -0,0 +1,28 @@
// Copyright (c) 2023 IBM Corp.
// All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package iooption
import (
"context"
G "github.com/IBM/fp-go/iooption/generic"
L "github.com/IBM/fp-go/lazy"
)
// WithLock executes the provided IO operation in the scope of a lock
func WithLock[E, A any](lock L.Lazy[context.CancelFunc]) func(fa IOOption[A]) IOOption[A] {
return G.WithLock[IOOption[A]](lock)
}

34
readerio/generic/sync.go Normal file
View File

@@ -0,0 +1,34 @@
// Copyright (c) 2023 IBM Corp.
// All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package generic
import (
"context"
F "github.com/IBM/fp-go/function"
G "github.com/IBM/fp-go/io/generic"
)
// WithLock executes the provided IO operation in the scope of a lock
func WithLock[GEA ~func(R) GIOA, GIOA ~func() A, R, A any](lock func() context.CancelFunc) func(fa GEA) GEA {
l := G.WithLock[GIOA](lock)
return func(fa GEA) GEA {
return F.Flow2(
fa,
l,
)
}
}

27
readerio/sync.go Normal file
View File

@@ -0,0 +1,27 @@
// Copyright (c) 2023 IBM Corp.
// All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package readerio
import (
"context"
G "github.com/IBM/fp-go/readerio/generic"
)
// WithLock executes the provided IO operation in the scope of a lock
func WithLock[R, A any](lock func() context.CancelFunc) func(fa ReaderIO[R, A]) ReaderIO[R, A] {
return G.WithLock[ReaderIO[R, A]](lock)
}

View File

@@ -17,7 +17,7 @@ package generic
import (
ET "github.com/IBM/fp-go/either"
G "github.com/IBM/fp-go/internal/file"
G "github.com/IBM/fp-go/internal/bracket"
I "github.com/IBM/fp-go/readerio/generic"
)

View File

@@ -0,0 +1,28 @@
// Copyright (c) 2023 IBM Corp.
// All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package generic
import (
"context"
ET "github.com/IBM/fp-go/either"
G "github.com/IBM/fp-go/readerio/generic"
)
// WithLock executes the provided IO operation in the scope of a lock
func WithLock[GEA ~func(R) GIOA, GIOA ~func() ET.Either[E, A], R, E, A any](lock func() context.CancelFunc) func(fa GEA) GEA {
return G.WithLock[GEA](lock)
}

27
readerioeither/sync.go Normal file
View File

@@ -0,0 +1,27 @@
// Copyright (c) 2023 IBM Corp.
// All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package readerioeither
import (
"context"
G "github.com/IBM/fp-go/readerioeither/generic"
)
// WithLock executes the provided IO operation in the scope of a lock
func WithLock[R, E, A any](lock func() context.CancelFunc) func(fa ReaderIOEither[R, E, A]) ReaderIOEither[R, E, A] {
return G.WithLock[ReaderIOEither[R, E, A]](lock)
}

View File

@@ -1,3 +1,3 @@
@echo off
mkdir build 2> NUL
gotip test .\... && go1.20.1 test .\... && go test -v -coverprofile build/cover.out -coverpkg=./... -covermode=atomic .\...
gotip test .\... && go1.20.5 test .\... && go test -v -coverprofile build/cover.out -coverpkg=./... -covermode=atomic .\...