Skip to content
This repository was archived by the owner on Nov 14, 2024. It is now read-only.

Commit 54014ae

Browse files
absolute links and redirects
1 parent f1afa69 commit 54014ae

27 files changed

+65
-65
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ The bundler will automatically update as you modify content.
1616

1717
All articles are in the `_posts` directory. To add a new article, create a new file with the name `yyyy-mm-dd-title-of-the-article.md`. Jekyll will use the date in the filename and the front matter (described shortly) to automatically sort articles and search by date.
1818

19-
All files are Markdown, with a header that looks like this (example from one of the articles):
19+
All files are Markdown, with a header that looks like below (example from one of the articles). Just copy everything and change the title, tags and excerpt
2020

2121
```
2222
---

_drafts/2021-09-14-scalac.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ Pattern matching is one Scala-specific feature that has been around for more tha
6868

6969
Learn what a pattern matching expression is and why it's useful. Deconstruct case classes and constants first, that will cover 90% of your use case in practice.
7070

71-
After that, if you have some spare time and you're ready to show off to your Scala teammates, learn some [nifty tricks](https://blog.rockthejvm.com/8-pm-tricks/) with pattern matching.
71+
After that, if you have some spare time and you're ready to show off to your Scala teammates, learn some [nifty tricks](/8-pm-tricks/) with pattern matching.
7272

7373
At this point, you can be a productive Scala developer for simple to medium projects. The topics above are what I teach in my [Scala 3 Essentials](https://rockthejvm.com/p/scala) course on Rock the JVM, and you can also follow the above steps on your own to learn by yourself in just a day of focused work.
7474

_posts/2020-10-12-spark-broadcast-joins.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ Brilliant - all is well. Except it takes a bloody ice age to run.
8383

8484
Why does the above join take so long to run?
8585

86-
If you ever want to debug performance problems with your Spark jobs, you'll need to know how to [read query plans](https://blog.rockthejvm.com/reading-query-plans/), and that's what we are going to do here as well. Let's have a look at this job's query plan so that we can see the operations Spark will perform as it's computing our innocent join:
86+
If you ever want to debug performance problems with your Spark jobs, you'll need to know how to [read query plans](/reading-query-plans/), and that's what we are going to do here as well. Let's have a look at this job's query plan so that we can see the operations Spark will perform as it's computing our innocent join:
8787

8888
```scala
8989
joined.explain()

_posts/2020-11-02-scala-3-indentation.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ def computeMeaningOfLife(year: Int): Int =
105105

106106
This part may be particularly confusing. The way I like to talk about it is: imagine the compiler inserted braces between `=` and your returned value; in this way, the implementation of the method is a _code block_, which, obviously, is a single expression whose value is given by its last constituent expression. The significant indentation means, in this case, that we actually have an invisible code block there.
107107

108-
An indentation region is also created when we define classes, traits, objects or [enums](https://blog.rockthejvm.com/enums-scala-3/) followed by a colon `:` and a line break. This token is now interpreted by the compiler as "colon at end of line", which is to say "colon then define everything indented". Examples:
108+
An indentation region is also created when we define classes, traits, objects or [enums](/enums-scala-3/) followed by a colon `:` and a line break. This token is now interpreted by the compiler as "colon at end of line", which is to say "colon then define everything indented". Examples:
109109

110110
```scala3
111111
class Animal:

_posts/2021-06-07-http4s-tutorial.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ def directorRoutes[F[_] : Monad]: HttpRoutes[F] = {
238238

239239
**The routes defined using the http4s DSL are composable**. So, it means that we can define them in different modules and then compose them in a single `HttpRoutes[F]` object. As developers, we know how vital module compositionality is for code that is easily maintainable and evolvable.
240240

241-
The trick is that the type `HttpRoutes[F]`, being an instance of the `Kleisli` type, is also a [`Semigroup`](https://blog.rockthejvm.com/semigroups-and-monoids-in-scala/). In fact, it's a `SemigroupK`, as we have a semigroup of an effect (remember the `F[_]` type constructor).
241+
The trick is that the type `HttpRoutes[F]`, being an instance of the `Kleisli` type, is also a [`Semigroup`](/semigroups-and-monoids-in-scala/). In fact, it's a `SemigroupK`, as we have a semigroup of an effect (remember the `F[_]` type constructor).
242242

243243
The main feature of semigroups is the definition of the `combine` function which, given two elements of the semigroup, returns a new element also belonging to the semigroup. For the `SemigroupK` type class, the function is called`combineK` or `<+>`.
244244

@@ -335,7 +335,7 @@ The `sanitized` attribute may safely be displayed to a client to describe an err
335335

336336
Instead, the `leftMap` function comes as an extension method of the Cats `Bifunctor` type class. When the type class is instantiated for the `Either` type, it provides many useful methods as `leftMap`, which eventually applies the given function to a `Left` value.
337337

338-
Finally, the `OptionalValidatingQueryParamDecoderMatcher[T]` returns the result of the validation process as an instance of the type `Validated[E, A]`. [`Validated[E, A]`](https://blog.rockthejvm.com/idiomatic-error-handling-in-scala/#4-advanced-validated) is a type coming from the Cats library representing the result of a validation process: If the process ends successfully, the `Validated` contains instance of type `A`, errors of type `E` otherwise. Moreover, we use `Validated[E, A]` in opposition to `Either[E, A]`, for example, because it accumulates errors by design. In our example, the _matcher_ returns an instance of `Validated[ParseFailure, Year]`.
338+
Finally, the `OptionalValidatingQueryParamDecoderMatcher[T]` returns the result of the validation process as an instance of the type `Validated[E, A]`. [`Validated[E, A]`](/idiomatic-error-handling-in-scala/#4-advanced-validated) is a type coming from the Cats library representing the result of a validation process: If the process ends successfully, the `Validated` contains instance of type `A`, errors of type `E` otherwise. Moreover, we use `Validated[E, A]` in opposition to `Either[E, A]`, for example, because it accumulates errors by design. In our example, the _matcher_ returns an instance of `Validated[ParseFailure, Year]`.
339339

340340
Once validated the query parameter, we can introduce the code handling the failure with a `BadRequest` HTTP status:
341341

_posts/2021-06-24-zio-fibers.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ _Another great round by [Riccardo Cardin](https://github.com/rcardin), a proud s
1111

1212
_Enter Riccardo:_
1313

14-
Many libraries implement the effect pattern in the Scala ecosystem: Cats Effect, Monix, and ZIO, just to list some. Each of these implements its own concurrency model. For example. Cats Effect and ZIO both rely on _fibers_. In the articles [Cats Effect 3 - Introduction to Fibers](https://blog.rockthejvm.com/cats-effect-fibers/) and [Cats Effect 3 - Racing IOs](https://blog.rockthejvm.com/cats-effect-racing-fibers/), we introduced the fiber model adopted by the Cats Effect library. Now, it's time to analyze the ZIO library and its implementation of the fiber model.
14+
Many libraries implement the effect pattern in the Scala ecosystem: Cats Effect, Monix, and ZIO, just to list some. Each of these implements its own concurrency model. For example. Cats Effect and ZIO both rely on _fibers_. In the articles [Cats Effect 3 - Introduction to Fibers](/cats-effect-fibers/) and [Cats Effect 3 - Racing IOs](/cats-effect-racing-fibers/), we introduced the fiber model adopted by the Cats Effect library. Now, it's time to analyze the ZIO library and its implementation of the fiber model.
1515

1616
## 1. Background and Setup
1717

_posts/2021-08-19-zio-kafka.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ So, let's proceed without further ado.
1919

2020
## 1. Background
2121

22-
Following this article will require a basic understanding of how Kafka works. Moreover, we should know what the effect pattern is and how ZIO implements it (refer to [ZIO: Introduction to Fibers](https://blog.rockthejvm.com/zio-fibers/), and to [Organizing Services with ZIO and ZLayers](https://blog.rockthejvm.com/structuring-services-with-zio-zlayer/) for further details).
22+
Following this article will require a basic understanding of how Kafka works. Moreover, we should know what the effect pattern is and how ZIO implements it (refer to [ZIO: Introduction to Fibers](/zio-fibers/), and to [Organizing Services with ZIO and ZLayers](/structuring-services-with-zio-zlayer/) for further details).
2323

2424
Apache Kafka is the standard de-facto within messaging systems. **Every Kafka installation has a broker, or a cluster of brokers, which allows its clients to write and read messages in a structure called _topic_, which are essentially distributed queues**. The clients writing into topics are called _producers_, whereas _consumers_ read information from topics.
2525

@@ -190,7 +190,7 @@ In this particular case, we obtain an instance of an `RManaged`, that in the ZIO
190190

191191
In fact, ZIO internally uses such a service to manage the connection pool to the broker for a consumer.
192192

193-
Last but not least, we create a `ZLayer` from the `managedConsumer`, allowing us to provide it as a service to any component depending on it (for a comprehensive introduction to the `ZLayer` type, please refer to the article [Organizing Services with ZIO and ZLayers](https://blog.rockthejvm.com/structuring-services-with-zio-zlayer/)):
193+
Last but not least, we create a `ZLayer` from the `managedConsumer`, allowing us to provide it as a service to any component depending on it (for a comprehensive introduction to the `ZLayer` type, please refer to the article [Organizing Services with ZIO and ZLayers](/structuring-services-with-zio-zlayer/)):
194194

195195
```scala
196196
val consumer: ZLayer[Clock with Blocking, Throwable, Consumer] =
@@ -641,7 +641,7 @@ Hence, the produced effect requests a `Producer[Any, UUID, Match]` as environmen
641641
producerEffect.provideSomeLayer(producer).exitCode
642642
```
643643

644-
We can compose the production of the messages and the consumption directly in one program using _fibers_ (see [ZIO: Introduction to Fibers](https://blog.rockthejvm.com/zio-fibers/) for further details on ZIO fibers):
644+
We can compose the production of the messages and the consumption directly in one program using _fibers_ (see [ZIO: Introduction to Fibers](/zio-fibers/) for further details on ZIO fibers):
645645

646646
```scala
647647
val program = for {

_posts/2021-10-21-kafka-streams.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ import java.util.Properties
5454
import scala.concurrent.duration._
5555
```
5656

57-
We will use version 2.8.0 of Kafka. As we've done in the article [ZIO Kafka: A Practical Streaming Tutorial](https://blog.rockthejvm.com/zio-kafka/), we will start the Kafka broker using a Docker container, declared through a `docker-compose.yml` file:
57+
We will use version 2.8.0 of Kafka. As we've done in the article [ZIO Kafka: A Practical Streaming Tutorial](/zio-kafka/), we will start the Kafka broker using a Docker container, declared through a `docker-compose.yml` file:
5858

5959
```yaml
6060
version: '2'
@@ -186,7 +186,7 @@ If we want to create any structure on top of Kafka topics, such as stream, we ne
186186

187187
What's a `Serde`? The `Serde` word stands for `Serializer` and `Deserializer`. A `Serde` provides the logic to read and write a message from and to a Kafka topic.
188188

189-
So, if we have a `Serde[R]` instance, we can deserialize and serialize objects of the type `R`. In this article, we will use JSON format for the payload of Kafka messages. In Scala, one of the most used libraries to marshall and unmarshall JSON into objects is Circe. We already talked about Circe in the post [Unleashing the Power of HTTP Apis: The Http4s Library](https://blog.rockthejvm.com/http4s-tutorial/), when we used it together with the Http4s library.
189+
So, if we have a `Serde[R]` instance, we can deserialize and serialize objects of the type `R`. In this article, we will use JSON format for the payload of Kafka messages. In Scala, one of the most used libraries to marshall and unmarshall JSON into objects is Circe. We already talked about Circe in the post [Unleashing the Power of HTTP Apis: The Http4s Library](/http4s-tutorial/), when we used it together with the Http4s library.
190190

191191
```scala
192192
// Scala Kafka Streams library

_posts/2021-12-28-doobie.md

+5-5
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ The above configuration defines a Postgres instance listening on port 5432 and h
6262

6363
Moreover, we define an Adminer instance listening on port 8080. Adminer is a web interface to Postgres, which we will use to create a database, some tables, and populate them with some data.
6464

65-
Next, we need a use case to train our skills about Doobie. We will use the same use case we introduced in the article [Unleashing the Power of HTTP Apis: The Http4s Library](https://blog.rockthejvm.com/http4s-tutorial/), which is implementing a small IMDB-like web service. The primary domain objects of the service are movies, actors, and directors. The goal is to use Doobie to interact with these tables through queries, insertion, and updates.
65+
Next, we need a use case to train our skills about Doobie. We will use the same use case we introduced in the article [Unleashing the Power of HTTP Apis: The Http4s Library](/http4s-tutorial/), which is implementing a small IMDB-like web service. The primary domain objects of the service are movies, actors, and directors. The goal is to use Doobie to interact with these tables through queries, insertion, and updates.
6666

6767
Inside Postgres, we will model the domain objects as tables and define their relations as foreign keys. The tables will be named `movies`, `actors`, and `directors`:
6868

@@ -238,7 +238,7 @@ def findAllActorsNamesProgram: IO[List[String]] = {
238238

239239
As it's the first query we make, the code is really verbose. However, we can analyze every aspect of a query in this way.
240240

241-
First, the `sql` [interpolator](https://blog.rockthejvm.com/how-to-create-your-own-string-interpolator/) allows us to create SQL statement fragments (more to come). Next, the method `query` lets us create a type that maps the single-row result of the query in a Scala type. The class is called `Query0[A]`. To accumulate results into a list, we use the `to[List]` method, which creates a `ConnectionIO[List[String]]`.
241+
First, the `sql` [interpolator](/how-to-create-your-own-string-interpolator/) allows us to create SQL statement fragments (more to come). Next, the method `query` lets us create a type that maps the single-row result of the query in a Scala type. The class is called `Query0[A]`. To accumulate results into a list, we use the `to[List]` method, which creates a `ConnectionIO[List[String]]`.
242242

243243
The `ConnectionIO[A]` type is interesting since it introduces a typical pattern used in the Doobie library. In fact, **Doobie defines all its most essential types as instances of the [`Free` monad](https://typelevel.org/cats/datatypes/freemonad.html)**.
244244

@@ -307,7 +307,7 @@ val actorsNamesStream: fs2.Stream[doobie.ConnectionIO, String] =
307307
sql"select name from actors".query[String].stream
308308
```
309309

310-
The `stream` method on the type `Query0` returns a `Stream[ConnectionIO, A]` which means a stream containing instances of type `A`, wrapped in an effect of type `ConnectionIO` (for a brief explanation of the Effect pattern, please refer to [The Effect Pattern](https://blog.rockthejvm.com/zio-fibers/#2-the-effect-pattern)).
310+
The `stream` method on the type `Query0` returns a `Stream[ConnectionIO, A]` which means a stream containing instances of type `A`, wrapped in an effect of type `ConnectionIO` (for a brief explanation of the Effect pattern, please refer to [The Effect Pattern](/zio-fibers/#2-the-effect-pattern)).
311311

312312
Once we obtained an instance of a `Stream`, we can decide to return it to the caller as it is, or to compile it into a finite type, such as `List[String]` or `Vector[String]`:
313313

@@ -403,7 +403,7 @@ def findActorsByInitialLetterUsingFragmentsProgram(initialLetter: String): IO[Li
403403
}
404404
```
405405

406-
In the example above, we build the three parts of the SQL statements, and then we combine them to produce the final query using the `++` operator. It's easy to understand why `Fragment` is also a `Monoid` since it's possible to use the `++` operator to define the `combine` function of monoids (more on the article [Semigroups and Monoids in Scala](https://blog.rockthejvm.com/semigroups-and-monoids-in-scala/)):
406+
In the example above, we build the three parts of the SQL statements, and then we combine them to produce the final query using the `++` operator. It's easy to understand why `Fragment` is also a `Monoid` since it's possible to use the `++` operator to define the `combine` function of monoids (more on the article [Semigroups and Monoids in Scala](/semigroups-and-monoids-in-scala/)):
407407

408408
```scala
409409
// Doobie library's code
@@ -615,7 +615,7 @@ Doobie defines the instances of the above type classes for the following types (
615615
* `Instant`, `LocalDate`, `LocalTime`, `LocalDateTime`, `OffsetTime`, `OffsetDateTime` and `ZonedDateTime` from the `java.time` package; and
616616
* single-element case classes wrapping one of the above types.
617617

618-
Deriving the `Get` and `Put` type classes for types that don't fit into one of the above categories is relatively easy. To create a concrete example, we introduce in our project the [estatico/scala-newtype](https://github.com/estatico/scala-newtype), which allows creating a new type that is a subtype of the original type but with a different name. The description of newtypes is far beyond the scope of this article, but you can find a good introduction on [Value Classes in Scala](https://blog.rockthejvm.com/value-classes/).
618+
Deriving the `Get` and `Put` type classes for types that don't fit into one of the above categories is relatively easy. To create a concrete example, we introduce in our project the [estatico/scala-newtype](https://github.com/estatico/scala-newtype), which allows creating a new type that is a subtype of the original type but with a different name. The description of newtypes is far beyond the scope of this article, but you can find a good introduction on [Value Classes in Scala](/value-classes/).
619619

620620
First, let's create a newtype wrapper around an actor name:
621621

_posts/2022-02-10-fs2.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ The `fs2-core` library provides the core functionalities of the library. Many ot
3030

3131
To work well with fs2, you'll need to be comfortable with Scala, of course. Some basics of Cats Effect would be wonderful. Rock the JVM has this in-depth [Cats Effect course](https://rockthejvm.com/p/cats-effect) if you're interested in mastering it, but it's not required.
3232

33-
It's usual for us at Rock the JVM to build the examples around a concrete scenario. We can continue to refer to the _myimdb_ project that we used both in the articles on [_http4s_](https://blog.rockthejvm.com/http4s-tutorial/) and on [_doobie_](https://blog.rockthejvm.com/doobie/).
33+
It's usual for us at Rock the JVM to build the examples around a concrete scenario. We can continue to refer to the _myimdb_ project that we used both in the articles on [_http4s_](/http4s-tutorial/) and on [_doobie_](/doobie/).
3434

3535
So, we define the Scala class that represents an actor inside a hypothetical movie database:
3636

_posts/2022-08-16-zio-http.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -856,7 +856,7 @@ SaRcAsM Is hArD To cOnVeY On tHe iNtErNeT
856856
Streaming responses is handled via `ZStream`, and works straight forwardly, if
857857
you are comfortable with that topic. If you would like to dig into `ZStream`s a
858858
bit further, I suggest you check out this
859-
[article](https://blog.rockthejvm.com/zio-streams/).
859+
[article](/zio-streams/).
860860
861861
In our example below, we take a `String` sentence, and repeat it 1000 times to
862862
bulk it up a bit, being sure to use the `HTTP_CHARSET` encoding when we create a

0 commit comments

Comments
 (0)