Skip to content

Commit 579cf20

Browse files
authored
DelayedQueue for Scala (sub-project) (#17)
1 parent 32ff924 commit 579cf20

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+5156
-91
lines changed
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
---
2+
name: cats-effect-io
3+
description: Scala functional programming with Cats Effect IO and typeclasses. Use for wrapping side effects, modeling purity, choosing Sync/Async/Temporal/Concurrent, handling blocking I/O, and composing resources, fibers, and concurrency safely.
4+
---
5+
6+
# Cats Effect IO (Scala)
7+
8+
## Quick start
9+
- Treat every side effect as an effect value: return `IO[A]`, `SyncIO[A]`, or `F[A]` with `F[_]: Sync`/`Async`/`Temporal` as needed.
10+
- Wrap Java blocking calls with `IO.blocking` or `IO.interruptible` (or `Sync[F].blocking`/`interruptible`).
11+
- Use `Resource` to acquire/release resources and `IOApp` for program entry points.
12+
- Prefer structured concurrency (`parTraverse`, `parMapN`, `background`, `Supervisor`) over manual fiber management.
13+
- Read `references/cats-effect-io.md` for concepts, recipes, and FAQ guidance.
14+
- For deeper `Resource` guidance, use the `cats-effect-resource` skill (install: `npx skills add https://github.com/alexandru/skills --skill cats-effect-resource`).
15+
16+
## Workflow
17+
1. Classify side effects and choose the effect type: `IO` directly or polymorphic `F[_]` with the smallest required Cats Effect typeclass (`Sync`, `Async`, `Temporal`, `Concurrent`).
18+
2. Wrap side-effectful code using `IO(...)`, `IO.blocking`, `IO.interruptible`, or `IO.async` (or their `Sync`/`Async` equivalents).
19+
3. Manage resources with `Resource` or `bracket` and keep acquisition/release inside effects.
20+
4. Compose effects with `flatMap`/for-comprehensions and collection combinators (`traverse`, `parTraverse`).
21+
5. Use concurrency primitives (`Ref`, `Deferred`, `Queue`, `Semaphore`, `Supervisor`) and structured concurrency to avoid fiber leaks.
22+
23+
## Side-effect rules (apply to `IO`, `SyncIO`, and to `F[_]: Sync/Async`)
24+
- All side-effectful functions must return results wrapped in `IO` (or `F[_]` with Cats Effect typeclasses).
25+
- Side-effects include all non-determinism (call sites are not referentially transparent):
26+
- Any I/O (files, sockets, console, databases).
27+
- `Instant.now()`, `Random.nextInt()`.
28+
- Any read from shared mutable state (the read itself is the side effect).
29+
- Returning mutable data structures (for example, `Array[Int]`).
30+
31+
## Blocking I/O rules
32+
- Java blocking methods must be wrapped in `IO.blocking` or `IO.interruptible` (or `Sync[F].blocking`/`interruptible`) so they run on the blocking pool.
33+
- Prefer `IO.interruptible` for methods that may throw `InterruptedException` or `IOException`, but not for resource disposal.
34+
- Use `IO.blocking` for cleanup/disposal (`Closeable#close`, `AutoCloseable#close`).
35+
36+
## Output expectations
37+
- Make side effects explicit in signatures (`IO`/`SyncIO` or `F[_]: Sync/Async`); the guidance here applies equally to concrete `IO` and polymorphic `F[_]`.
38+
- Use the smallest typeclass constraint that supports the needed operations.
39+
- Keep effects as values; do not execute effects in constructors or top-level vals.
40+
41+
## References
42+
- Load `references/cats-effect-io.md` for documentation summary and patterns.
43+
- For concrete samples, read `references/cats-effect-io.md`.
44+
- Use the `cats-effect-resource` skill for Resource-specific workflows and patterns (install: `npx skills add https://github.com/alexandru/skills --skill cats-effect-resource`).
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
# Cats Effect IO and Typeclasses (Scala)
2+
3+
Sources:
4+
- https://typelevel.org/cats-effect/docs/tutorial
5+
- https://typelevel.org/cats-effect/docs/concepts
6+
- https://typelevel.org/cats-effect/docs/recipes
7+
- https://typelevel.org/cats-effect/docs/faq
8+
9+
## Core ideas
10+
- **Effects as values**: `IO[A]` (or `F[A]`) describes side effects; nothing runs until the effect is evaluated.
11+
- **Fibers** are lightweight threads; use structured concurrency (`parMapN`, `parTraverse`) instead of manual `start`/`join`.
12+
- **Cancelation** is cooperative and always runs finalizers; use `Resource` to ensure cleanup under success, error, or cancel.
13+
- **Asynchronous vs synchronous**: `IO.async` uses callbacks; `IO.delay`/`IO.blocking`/`IO.interruptible` use synchronous execution.
14+
15+
## Blocking and interruptibility
16+
- `IO.blocking` (or `Sync[F].blocking`) moves blocking JVM calls onto the blocking pool.
17+
- `IO.interruptible` allows cancelation via thread interruption when the underlying API supports it.
18+
- Many `java.io` reads ignore interruption; use explicit cancelation protocols when available.
19+
20+
## Resource safety
21+
- Prefer `Resource` over manual `try/finally` for acquisition/release.
22+
- Use `Resource.fromAutoCloseable` for simple `AutoCloseable` lifecycles; use `Resource.make` when you need custom release handling.
23+
24+
## Common recipes
25+
- **Background work**: use `Supervisor` for start-and-forget fibers with safe cleanup.
26+
- **Effectful loops**: use `traverse`/`traverse_` and `parTraverse` for sequencing or parallelism.
27+
- **Shared state**: use `Ref`, `Deferred`, and other std primitives (avoid mutable state).
28+
29+
## API samples (IO and F[_])
30+
31+
Side effects as values (IO vs F[_]):
32+
```scala
33+
import cats.effect.{IO, Sync}
34+
35+
def nowIO: IO[Long] = IO(java.time.Instant.now().toEpochMilli)
36+
37+
def nowF[F[_]: Sync]: F[Long] =
38+
Sync[F].delay(java.time.Instant.now().toEpochMilli)
39+
```
40+
41+
Polymorphic side effects:
42+
```scala
43+
import cats.effect.Sync
44+
45+
def readEnv[F[_]: Sync](key: String): F[Option[String]] =
46+
Sync[F].delay(sys.env.get(key))
47+
```
48+
49+
Blocking vs interruptible:
50+
```scala
51+
import cats.effect.{IO, Sync}
52+
53+
import java.io.FileInputStream
54+
55+
def readByteIO(path: String): IO[Int] =
56+
IO.blocking(new FileInputStream(path)).bracket { in =>
57+
IO.interruptible(in.read())
58+
} { in =>
59+
IO.blocking(in.close())
60+
}
61+
62+
val blockingCall: IO[Unit] = IO.blocking {
63+
java.nio.file.Files.list(java.nio.file.Paths.get("/tmp")).close()
64+
}
65+
66+
def interruptibleSleep[F[_]: Sync]: F[Unit] =
67+
Sync[F].interruptible(Thread.sleep(250))
68+
```
69+
70+
Resource usage:
71+
```scala
72+
import cats.effect.{IO, Resource}
73+
import java.io.FileInputStream
74+
75+
def inputStream(path: String): Resource[IO, FileInputStream] =
76+
Resource.fromAutoCloseable(IO.blocking(new FileInputStream(path)))
77+
78+
def readFirstByte(path: String): IO[Int] =
79+
inputStream(path).use(in => IO.interruptible(in.read()))
80+
```
81+
82+
Structured concurrency:
83+
```scala
84+
import cats.effect.{IO, IOApp}
85+
import cats.syntax.all._
86+
87+
object ParallelExample extends IOApp.Simple {
88+
val run: IO[Unit] =
89+
(IO.println("A"), IO.println("B")).parTupled.void
90+
}
91+
```
92+
93+
## FAQ highlights
94+
- If an `IO` is created but not composed, it does not run; compiler warnings can help catch this.
95+
- `IO(...)` may run on a blocking thread in some optimized cases; this is normal.
96+
- Starvation warnings often indicate accidental blocking without `IO.blocking`.
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
---
2+
name: cats-effect-resource
3+
description: Scala resource lifecycle management with Cats Effect `Resource` and `IO`. Use when defining safe acquisition/release, composing resources (including parallel acquisition), or designing resource-safe APIs and cancellation behavior for files, streams, pools, clients, and background fibers.
4+
---
5+
6+
# Cats Effect Resource (Scala)
7+
8+
## Quick start
9+
- Model each resource with `Resource.make` or `Resource.fromAutoCloseable` and keep release idempotent.
10+
- Compose resources with `flatMap`, `mapN`, `parMapN`, or helper constructors; expose `Resource[F, A]` from APIs.
11+
- Use `Resource` at lifecycle boundaries and call `.use` only at the program edges.
12+
- Read `references/resource.md` for patterns, best practices, and API notes.
13+
14+
## Workflow
15+
1. Identify acquisition, use, and release steps; decide if acquisition is blocking.
16+
2. Implement a `Resource[F, A]` constructor using the smallest needed typeclass.
17+
3. Compose resources into higher-level resources and keep finalizers minimal.
18+
4. Decide how cancelation and errors should influence release logic.
19+
5. Run with `.use` at the boundary (IOApp, service startup) and avoid leaking raw `A`.
20+
21+
## Usage guidance
22+
- Prefer `Resource` over `try/finally` or `bracket` when composition and cancelation safety matter.
23+
- Use `IO.blocking` (or `Sync[F].blocking`) for acquisition and release when calling blocking JVM APIs.
24+
- For background fibers, use `Resource` or `Supervisor` to ensure cleanup on cancelation.
25+
26+
## References
27+
- Load `references/resource.md` for API details, patterns, and examples.
28+
- For Kotlin/Arrow parallels, see the `arrow-resource` skill.
29+
- Install this skill with `npx skills add https://github.com/alexandru/skills --skill cats-effect-resource`.
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
# Cats Effect Resource (Scala) - Practical Guide
2+
3+
Sources:
4+
- https://typelevel.org/cats-effect/docs/std/resource
5+
- https://github.com/typelevel/cats-effect/blob/series/3.x/kernel/shared/src/main/scala/cats/effect/kernel/Resource.scala
6+
7+
## Table of Contents
8+
- [Core model](#core-model)
9+
- [Core APIs](#core-apis)
10+
- [When to use Resource](#when-to-use-resource)
11+
- [Patterns](#patterns)
12+
- [Cancelation and error behavior](#cancelation-and-error-behavior)
13+
- [Interop and blocking](#interop-and-blocking)
14+
- [Checklist](#checklist)
15+
16+
## Core model
17+
- `Resource[F, A]` encodes acquisition and release with a `use` phase.
18+
- Release runs on success, error, or cancelation.
19+
- Acquisition and finalizers are sequenced and run in a controlled scope; release is LIFO.
20+
21+
## Core APIs
22+
- `Resource.make(acquire)(release)` for custom lifecycle.
23+
- `Resource.fromAutoCloseable` for `AutoCloseable` lifecycles.
24+
- `Resource.eval` to lift an effect into a resource.
25+
- `.use` to run the resource and ensure release.
26+
- `map`, `flatMap`, `mapN`, `parMapN`, `parZip` to compose resources.
27+
28+
## When to use Resource
29+
- You need safe cleanup under cancelation.
30+
- You need to compose resources and guarantee LIFO release.
31+
- You want an API that makes lifecycle explicit and testable.
32+
33+
## Patterns
34+
35+
### 1) Resource constructors
36+
Prefer functions that return `Resource[F, A]`:
37+
38+
```scala
39+
import cats.effect.{Resource, Sync}
40+
41+
final class UserProcessor {
42+
def start(): Unit = ()
43+
def shutdown(): Unit = ()
44+
}
45+
46+
def userProcessor[F[_]: Sync]: Resource[F, UserProcessor] =
47+
Resource.make(Sync[F].delay { new UserProcessor().tap(_.start()) })(p =>
48+
Sync[F].delay(p.shutdown())
49+
)
50+
```
51+
52+
### 2) Composing resources
53+
54+
```scala
55+
import cats.effect.{Resource, Sync}
56+
import cats.syntax.all._
57+
58+
final class DataSource { def connect(): Unit = (); def close(): Unit = () }
59+
final class Service(ds: DataSource, up: UserProcessor)
60+
61+
def dataSource[F[_]: Sync]: Resource[F, DataSource] =
62+
Resource.make(Sync[F].delay { new DataSource().tap(_.connect()) })(ds =>
63+
Sync[F].delay(ds.close())
64+
)
65+
66+
def service[F[_]: Sync]: Resource[F, Service] =
67+
(dataSource[F], userProcessor[F]).mapN(new Service(_, _))
68+
```
69+
70+
### 3) Parallel acquisition
71+
72+
```scala
73+
import cats.effect.{Resource, Sync}
74+
import cats.syntax.all._
75+
76+
def servicePar[F[_]: Sync]: Resource[F, Service] =
77+
(dataSource[F], userProcessor[F]).parMapN(new Service(_, _))
78+
```
79+
80+
### 4) File input stream
81+
82+
```scala
83+
import cats.effect.{IO, Resource}
84+
85+
import java.io.FileInputStream
86+
87+
def inputStream(path: String): Resource[IO, FileInputStream] =
88+
Resource.fromAutoCloseable(IO.blocking(new FileInputStream(path)))
89+
```
90+
91+
### 5) Database pool + per-connection resource
92+
93+
```scala
94+
import cats.effect.{Resource, Sync}
95+
96+
import javax.sql.DataSource
97+
98+
def pool[F[_]: Sync]: Resource[F, DataSource] = ???
99+
100+
def connection[F[_]: Sync](ds: DataSource): Resource[F, java.sql.Connection] =
101+
Resource.make(Sync[F].blocking(ds.getConnection))(c =>
102+
Sync[F].blocking(c.close())
103+
)
104+
```
105+
106+
### 6) Acquire in a loop
107+
Use `Resource.make` per element and compose with `traverse`/`parTraverse`:
108+
109+
```scala
110+
import cats.effect.{Resource, Sync}
111+
import cats.syntax.all._
112+
113+
def acquireOne[F[_]: Sync](id: String): Resource[F, Handle] = ???
114+
115+
def acquireAll[F[_]: Sync](ids: List[String]): Resource[F, List[Handle]] =
116+
ids.traverse(acquireOne[F])
117+
```
118+
119+
## Cancelation and error behavior
120+
- Finalizers run on success, error, or cancelation.
121+
- If finalizers can fail, decide whether to log, suppress, or raise secondary errors.
122+
- Keep finalizers idempotent and minimal to avoid cascading failures during release.
123+
124+
## Interop and blocking
125+
- Wrap blocking acquisition or release in `blocking` to avoid compute starvation.
126+
- Prefer `Resource.fromAutoCloseable` for Java interop; use `make` for custom release.
127+
- If the API supports cooperative cancellation, combine it with `Resource` to ensure cleanup.
128+
129+
## Checklist
130+
- Expose `Resource[F, A]` in public constructors.
131+
- Keep release idempotent and tolerant of partial failures.
132+
- Use `parMapN` only for independent resources.
133+
- Avoid calling `.use` except at lifecycle boundaries.
134+
- Use `IO.blocking`/`Sync[F].blocking` for blocking JVM APIs.
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
---
2+
name: cats-mtl-typed-errors
3+
description: Scala typed errors with Cats MTL Raise/Handle and allow/rescue. Use for designing custom domain error types without EitherT, while keeping Cats Effect and ecosystem composition. Covers Scala 2/3 syntax and IO-only or F[_] usage.
4+
---
5+
6+
# Cats MTL Typed Errors (Scala)
7+
8+
## Quick start
9+
- Define a domain error type; it may or may not extend Throwable depending on context.
10+
- Use Cats MTL `Raise[F, E]` in functions that can raise errors.
11+
- Use `Handle.allow`/`rescue` (Scala 3) or `Handle.allowF` (Scala 2) to introduce a scoped error capability and handle it like try/catch.
12+
- Prefer Cats MTL over `IO[Either[E, A]]` and avoid `EitherT[IO, E, A]`; pure functions returning `Either[E, A]` are fine at API boundaries.
13+
- `F[_]` is optional: you can write `IO`-specific code or keep `F[_]` for polymorphism, depending on the project.
14+
15+
## Workflow
16+
1. Model domain errors as sealed ADTs (Scala 2) or enums (Scala 3)
17+
2. For effectful code that can raise errors, require `Raise[F, E]` (and `Monad[F]` or `Applicative[F]`).
18+
3. Raise errors with `.raise` and return successful values with `pure`.
19+
4. At a boundary, use `Handle.allow` (Scala 3) or `Handle.allowF` (Scala 2) to create a scope where raises are valid.
20+
5. Close the scope with `.rescue` to handle each error case explicitly.
21+
6. Keep Cats Effect resource and concurrency semantics intact by staying in the monofunctor error channel.
22+
23+
## Patterns to apply
24+
- **Typed errors in signatures**: treat the error type parameter `E` as the checked-exception channel in the function signature.
25+
- **Scoped error capabilities**: require `Raise[F, E]` in functions that can fail; use `Handle[F, E]` when you also need to recover.
26+
- **Scala 3 ergonomics**: prefer `using` and context functions with `allow`; type inference is significantly better.
27+
- **Scala 2 compatibility**: use `allowF` and explicit implicit parameters; expect more braces and explicit types.
28+
- **Interop with pure code**: use pure `Either[E, A]` for parsing/validation and lift into `F` where needed.
29+
- **Avoid transformer stacks**: do not reach for `EitherT` just to get a typed error channel; Cats MTL provides the capability without the stack.
30+
- **Avoid sealed-on-sealed inheritance**: model error hierarchies with composition (wrapper case classes), not sealed inheritance chains.
31+
32+
## References
33+
- Load `references/custom-error-types.md` for detailed guidance, Scala 2/3 syntax, and rationale from the Typelevel article.

0 commit comments

Comments
 (0)