Skip to content

Commit

Permalink
Make the microsite compile again by updating to the Effect based Endp…
Browse files Browse the repository at this point in the history
…oints. This only commit only fixes docs/makeMicrosite and does not include updates to the written content of the documentation
  • Loading branch information
rpless authored Jun 1, 2020
1 parent 78b2f15 commit 5137cc4
Show file tree
Hide file tree
Showing 9 changed files with 94 additions and 99 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ local.*

.bloop
.metals
project/metals.sbt
3 changes: 2 additions & 1 deletion build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ lazy val docSettings = allSettings ++ Seq(
micrositeName := "Finch",
micrositeDescription := "Scala combinator library for building Finagle HTTP services",
micrositeAuthor := "Vladimir Kostyukov",
micrositeCompilingDocsTool := WithTut,
micrositeHighlightTheme := "atom-one-light",
micrositeHomepage := "https://finagle.github.io/finch/",
micrositeDocumentationUrl := "api",
Expand Down Expand Up @@ -342,7 +343,7 @@ lazy val docs = project
)
)
.enablePlugins(MicrositesPlugin, ScalaUnidocPlugin)
.dependsOn(core, circe, argonaut, iteratee, refined)
.dependsOn(core, circe, argonaut, iteratee, refined, fs2)

lazy val examples = project
.settings(moduleName := "finchx-examples")
Expand Down
23 changes: 12 additions & 11 deletions docs/src/main/tut/best-practices.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,18 +54,18 @@ class patchers are usually represented as `Endpoint[A => A]`, which

```tut:silent
import java.util.UUID
import cats.effect.IO
import io.finch._
import io.finch.circe._
import io.finch.syntax._
import io.finch.catsEffect._
import io.circe.generic.auto._
case class Todo(id: UUID, title: String, completed: Boolean, order: Int)
object Todo {
def list():List[Todo] = ???
}
val patchedTodo: Endpoint[Todo => Todo] = jsonBody[Todo => Todo]
val patchTodo: Endpoint[Todo] = patch("todos" :: path[UUID] :: patchedTodo) { (id: UUID, pt: Todo => Todo) =>
val patchedTodo: Endpoint[IO, Todo => Todo] = jsonBody[Todo => Todo]
val patchTodo: Endpoint[IO, Todo] = patch("todos" :: path[UUID] :: patchedTodo) { (id: UUID, pt: Todo => Todo) =>
val oldTodo = ??? // get by id
val newTodo = pt(oldTodo)
// store newTodo in the DB
Expand All @@ -87,8 +87,8 @@ import io.finch._
import io.finch.circe._
import io.circe.generic.auto._
val postedTodo: Endpoint[Todo] = jsonBody[UUID => Todo].map(_(UUID.randomUUID()))
val postTodo: Endpoint[Todo] = post("todos" :: postedTodo) { t: Todo =>
val postedTodo: Endpoint[IO, Todo] = jsonBody[UUID => Todo].map(_(UUID.randomUUID()))
val postTodo: Endpoint[IO, Todo] = post("todos" :: postedTodo) { t: Todo =>
// store t in the DB
Ok(t)
}
Expand All @@ -110,10 +110,10 @@ endpoints. Use `FuturePool`s to wrap expensive computations.

```tut:silent
import io.finch._
import io.finch.syntax._
import io.finch.catsEffect._
import com.twitter.util.FuturePool
val expensive: Endpoint[BigInt] = get(path[Int]) { i: Int =>
val expensive: Endpoint[IO, BigInt] = get(path[Int]) { i: Int =>
FuturePool.unboundedPool {
Ok(BigInt(i).pow(i))
}
Expand Down Expand Up @@ -170,6 +170,7 @@ One of the easiest things to export is a _counter_ that captures the number of t
occurred.

```tut:silent
import cats.effect.IO
import io.finch._
import io.finch.circe._
import io.circe.generic.auto._
Expand All @@ -179,7 +180,7 @@ import com.twitter.finagle.stats.Counter
object Main extends TwitterServer {
val todos: Counter = statsReceiver.counter("todos")
val postTodo: Endpoint[Todo] = post("todos" :: postedTodo) { t: Todo =>
val postTodo: Endpoint[IO, Todo] = post("todos" :: postedTodo) { t: Todo =>
todos.incr()
// add todo into the DB
Ok(t)
Expand All @@ -200,7 +201,7 @@ import com.twitter.finagle.stats.Stat
object Main extends TwitterServer {
val getTodosLatency: Stat = statsReceiver.stat("get_todos_latency")
val getTodos: Endpoint[List[Todo]] = get("todos") {
val getTodos: Endpoint[IO, List[Todo]] = get("todos") {
Stat.time(getTodosLatency) { Ok(Todo.list()) }
}
}
Expand Down Expand Up @@ -250,7 +251,7 @@ useful server-side features that might be useful for most of the use cases.
object Main extends TwitterServer {
val ping: Endpoint[String] = get("ping") { Ok("Pong") }
val ping: Endpoint[IO, String] = get("ping") { Ok("Pong") }
val service: Service[Request, Response] = ping.toServiceAs[Text.Plain]
def main(): Unit = {
Expand Down
1 change: 0 additions & 1 deletion docs/src/main/tut/contributing.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
---
layout: docs

---
Generally, Finch follows a standard [fork and pull][0] model for contributions via GitHub pull requests. Thus, the
_contributing process_ looks as follows:
Expand Down
80 changes: 38 additions & 42 deletions docs/src/main/tut/cookbook.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,15 +68,16 @@ cornerstone idea is to return a `Buf` instance from the endpoint so we could use
(where it's quite legal to return a `Future[Buf]`).

```tut:silent
import cats.effect._
import io.finch._
import io.finch.syntax._
import com.twitter.io.{Reader, Buf}
import io.finch.catsEffect._
import com.twitter.io.{Buf, BufReader, Reader}
import java.io.File
val reader: Reader = Reader.fromFile(new File("/dev/urandom"))
val reader: Reader[Buf] = Reader.fromFile(new File("/dev/urandom"))
val file: Endpoint[Buf] = get("file") {
Reader.readAll(reader).map(Ok)
val file: Endpoint[IO, Buf] = get("file") {
BufReader.readAll(reader).map(Ok)
}
```

Expand All @@ -88,18 +89,19 @@ It's also possible to _stream_ the file content to the client using [`AsyncStrea

```tut:silent
import io.finch._
import io.finch.syntax._
import com.twitter.conversions.storage._
import io.finch.catsEffect._
import com.twitter.conversions.StorageUnitOps._
import com.twitter.concurrent.AsyncStream
import com.twitter.finagle.Http
import com.twitter.io.{Reader, Buf}
import com.twitter.io.{Buf, BufReader, Reader}
import java.io.File
val reader: Reader = Reader.fromFile(new File("/dev/urandom"))
val reader: Reader[Buf] = Reader.fromFile(new File("/dev/urandom"))
val file: Endpoint[AsyncStream[Buf]] = get("stream-of-file") {
Ok(AsyncStream.fromReader(reader, chunkSize = 512.kilobytes.inBytes.toInt))
val file: Endpoint[IO, AsyncStream[Buf]] = get("stream-of-file") {
val chunkedReader = BufReader.chunked(reader, chunkSize = 512.kilobytes.inBytes.toInt)
Ok(Reader.toAsyncStream(chunkedReader))
}
```

Expand Down Expand Up @@ -141,7 +143,7 @@ An `Endpoint[Unit]` represents an endpoint that doesn't return any payload in th
```tut:silent
import io.finch._
val empty: Endpoint[Unit] = get("empty" :: path[String]) { s: String =>
val empty: Endpoint[IO, Unit] = get("empty" :: path[String]) { s: String =>
NoContent[Unit].withHeader("X-String" -> s)
}
```
Expand All @@ -157,13 +159,13 @@ import com.twitter.finagle.http.Status
case class Foo(s: String)
// This is possible
val fooOrEmpty: Endpoint[Foo] = get("foo" :: path[String]) { s: String =>
val fooOrEmpty: Endpoint[IO, Foo] = get("foo" :: path[String]) { s: String =>
if (s != "") Ok(Foo(s))
else NoContent
}
// This is recommended
val fooOrFailure: Endpoint[Foo] = get("foo" :: path[String]) { s: String =>
val fooOrFailure: Endpoint[IO, Foo] = get("foo" :: path[String]) { s: String =>
if (s != "") Ok(Foo(s))
else BadRequest(new IllegalArgumentException("empty string"))
}
Expand All @@ -179,7 +181,7 @@ output) indicating that there is no payload returned.
import io.finch._
import com.twitter.finagle.http.Status
val redirect: Endpoint[Unit] = get("redirect" :: "from") {
val redirect: Endpoint[IO, Unit] = get("redirect" :: "from") {
Output.unit(Status.SeeOther).withHeader("Location" -> "/redirect/to")
}
```
Expand Down Expand Up @@ -209,9 +211,9 @@ import io.finch._
case class Foo(i: Int, s: String)
val foo: Endpoint[Foo] = (param[Int]("i") :: param("s")).as[Foo]
val foo: Endpoint[IO, Foo] = (param[Int]("i") :: param("s")).as[Foo]
val getFoo: Endpoint[Foo] = get("foo" :: foo) { f: Foo =>
val getFoo: Endpoint[IO, Foo] = get("foo" :: foo) { f: Foo =>
println(s"Got foo: $f")
Ok(f) // echo it back
}
Expand All @@ -237,15 +239,15 @@ import io.finch._
case class User(id: Int)
val auth: Endpoint[User] = header("User").mapOutput(u =>
val auth: Endpoint[IO, User] = header("User").mapOutput(u =>
if (u == "secret user") Ok(User(10))
else Unauthorized(new Exception(s"User $u is unknown."))
).handle {
// if header "User" is missing we respond 401
case e: Error.NotPresent => Unauthorized(e)
}
val getCurrentUser: Endpoint[User] = get("user" :: auth) { u: User =>
val getCurrentUser: Endpoint[IO, User] = get("user" :: auth) { u: User =>
println(s"Got user: $u")
Ok(u) // echo it back
}
Expand All @@ -272,10 +274,10 @@ The previous example's `auth` endpoint can be updated as follows:
```tut:silent
import com.twitter.util.Future
def fetchUserForToken(token: String): Future[Option[User]] = ???
def fetchUserForToken(token: String): IO[Option[User]] = ???
val auth: Endpoint[User] = header("User").mapOutputAsync(u =>
if (u == "secret user") Future.value(Ok(User(10)))
val auth: Endpoint[IO, User] = header("User").mapOutputAsync(u =>
if (u == "secret user") IO.pure(Ok(User(10)))
else fetchUserForToken(u).map {
case Some(user) => Ok(user)
case None => Unauthorized(new Exception(s"Invalid token: $u"))
Expand All @@ -302,7 +304,7 @@ import java.time.LocalDateTime
implicit val e: DecodePath[LocalDateTime] =
DecodePath.instance(s => Try(LocalDateTime.parse(s)).toOption)
val dateTime: Endpoint[LocalDateTime] = get("time" :: path[LocalDateTime]) { t: LocalDateTime =>
val dateTime: Endpoint[IO, LocalDateTime] = get("time" :: path[LocalDateTime]) { t: LocalDateTime =>
println(s"Got time: $t")
Ok(t) // echo it back
}
Expand Down Expand Up @@ -340,8 +342,10 @@ import com.twitter.finagle.http.filter.Cors
import com.twitter.finagle.http.{Request, Response}
import com.twitter.finagle.Service
import io.finch._
import io.finch.catsEffect._
val service: Service[Request, Response] = Endpoint.liftOutput(Ok("Hello, world!")).toServiceAs[Text.Plain]
val service: Service[Request, Response] =
Endpoint.liftOutput[IO, String](Ok("Hello, world!")).toServiceAs[Text.Plain]
val policy: Cors.Policy = Cors.Policy(
allowsOrigin = _ => Some("*"),
Expand Down Expand Up @@ -416,7 +420,7 @@ Also note that as of [Finch 0.16-M3](https://github.com/finagle/finch/releases/t
is a Scala Futures syntax support for endpoints.

```tut:silent
import io.finch._, io.finch.syntax.scalaFutures._
import io.finch._, io.finch.catsEffect._
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
Expand All @@ -440,30 +444,22 @@ NOTE: SSE requires `Cache-Control` to be disabled.

```tut:silent
import cats.Show
import com.twitter.concurrent.AsyncStream
import com.twitter.conversions.time._
import com.twitter.finagle.Service
import com.twitter.finagle.http.{Request, Response}
import com.twitter.finagle.util.DefaultTimer
import com.twitter.util.{ Await, Future, Timer}
import io.finch._
import io.finch.sse._
import io.finch.fs2._
import _root_.fs2.Stream
import java.util.Date
import scala.concurrent.duration._
implicit val showDate: Show[Date] = Show.fromToString[Date]
implicit val timer: Timer = DefaultTimer
def streamTime(): AsyncStream[ServerSentEvent[Date]] =
AsyncStream.fromFuture(
Future.sleep(1.seconds)
.map(_ => new Date())
.map(ServerSentEvent(_))
) ++ streamTime()
implicit val timer: Timer[IO] = IO.timer(scala.concurrent.ExecutionContext.global)
def streamTime(): Stream[IO, ServerSentEvent[Date]] =
Stream.awakeEvery[IO](1.second).map(_ => new Date()).map(ServerSentEvent(_))
val time: Endpoint[AsyncStream[ServerSentEvent[Date]]] = get("time") {
Ok(streamTime())
.withHeader("Cache-Control" -> "no-cache")
val time: Endpoint[IO, Stream[IO, ServerSentEvent[Date]]] = get("time") {
Ok(streamTime()).withHeader("Cache-Control" -> "no-cache")
}
val service: Service[Request, Response] = time.toServiceAs[Text.EventStream]
Expand All @@ -484,7 +480,7 @@ import io.finch._
import io.finch.circe._
import io.circe.generic.auto._
val endpoint: Endpoint[Map[String, String]] = get("jsonp") {
val endpoint: Endpoint[IO, Map[String, String]] = get("jsonp") {
Ok(Map("foo" -> "bar"))
}
Expand Down
13 changes: 5 additions & 8 deletions docs/src/main/tut/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,7 @@
layout: home
title: "Home"
section: "home"
technologies:
- first: ["Scala", "sbt-microsites plugin is completely written in Scala"]
- second: ["SBT", "sbt-microsites plugin uses SBT and other sbt plugins to generate microsites easily"]
- third: ["Jekyll", "Jekyll allows for the transformation of plain text into static websites and blogs."]
position: 0
---

Finch provides a combinator API over the [Finagle][finagle] HTTP services. An `Endpoint[A]`, main
Expand All @@ -24,7 +21,7 @@ build.sbt:
libraryDependencies ++= Seq(
"com.github.finagle" %% "finch-core" % "0.32.1",
"com.github.finagle" %% "finch-circe" % "0.32.1",
"io.circe" %% "circe-generic" % "0.9.3"
"io.circe" %% "circe-generic" % "0.13.1"
)
```

Expand All @@ -33,10 +30,10 @@ Main.scala:
```tut:silent
import com.twitter.finagle.Http
import com.twitter.util.Await
import cats.effect.IO
import io.finch._
import io.finch.circe._
import io.finch.syntax._
import io.finch.catsEffect._
import io.circe.generic.auto._
object Main extends App {
Expand All @@ -47,7 +44,7 @@ object Main extends App {
def currentTime(l: java.util.Locale): String =
java.util.Calendar.getInstance(l).getTime.toString
val time: Endpoint[Time] =
val time: Endpoint[IO, Time] =
post("time" :: jsonBody[Locale]) { l: Locale =>
Ok(Time(l, currentTime(new java.util.Locale(l.language, l.country))))
}
Expand Down
Loading

0 comments on commit 5137cc4

Please sign in to comment.