Skip to content

Commit

Permalink
orgScriptCI task integration (#118)
Browse files Browse the repository at this point in the history
* orgScriptCI task integration.
Bumps sbt-org-policies integration.
Brings back the readme to the tut folder.

* Bumps to new version where badges are fixed
  • Loading branch information
juanpedromoreno authored Apr 27, 2017
1 parent da440e1 commit b088bdc
Show file tree
Hide file tree
Showing 6 changed files with 260 additions and 18 deletions.
7 changes: 2 additions & 5 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,8 @@ before_install:
-K $encrypted_37b99bd39158_key -iv $encrypted_37b99bd39158_iv
-in secring.gpg.enc -out secring.gpg -d; fi
script:
- sbt ++$TRAVIS_SCALA_VERSION clean compile test
- sbt ++$TRAVIS_SCALA_VERSION coverage 'fetchJVM/test' 'fetchJVM/coverageReport'
- sbt ++$TRAVIS_SCALA_VERSION 'docs/tut'
- sbt ++$TRAVIS_SCALA_VERSION 'readme/tut'
- sbt ++$TRAVIS_SCALA_VERSION orgScriptCI
- sbt 'examples/test'
after_success:
- bash <(curl -s https://codecov.io/bash) -t 47609994-e0cd-4f3b-a28d-eb558142c3bb
- bash <(curl -s https://codecov.io/bash)
- sbt ++$TRAVIS_SCALA_VERSION orgAfterCISuccess
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,5 @@ The process is simple:
5. Update the documentation
6. Submit pull request

You will be automatically included in the [AUTHORS.md](AUTHORS.md#contributors) file as contributor.
You will be automatically included in the [AUTHORS.md](AUTHORS.md#contributors) file as contributor in the next release.
If you encounter any confusion or frustration during the contribution process, please create a GitHub issue and we'll do our best to improve the process.
17 changes: 10 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

[comment]: # (Start Badges)

[![Join the chat at https://gitter.im/47deg/fetch](https://badges.gitter.im/47deg/fetch.svg)](https://gitter.im/47deg/fetch?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Build Status](https://travis-ci.org/47deg/fetch.svg?branch=master)](https://travis-ci.org/47deg/fetch) [![codecov.io](http://codecov.io/github/47deg/fetch/coverage.svg?branch=master)](http://codecov.io/github/47deg/fetch?branch=master) [![Maven Central](https://img.shields.io/badge/maven%20central-0.6.1-green.svg)](https://maven-badges.herokuapp.com/maven-central/com.47deg/fetch) [![License](https://img.shields.io/badge/license-Apache%202-blue.svg)](https://raw.githubusercontent.com/47deg/fetch/master/LICENSE) [![Latest version](https://index.scala-lang.org/47deg/fetch/fetch/latest.svg)](https://index.scala-lang.org/47deg/fetch/fetch) [![GitHub Issues](https://img.shields.io/github/issues/47deg/fetch.svg)](https://github.com/47deg/fetch/issues)
[![Join the chat at https://gitter.im/47deg/fetch](https://badges.gitter.im/47deg/fetch.svg)](https://gitter.im/47deg/fetch?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Build Status](https://travis-ci.org/47deg/fetch.svg?branch=master)](https://travis-ci.org/47deg/fetch) [![codecov.io](http://codecov.io/github/47deg/fetch/coverage.svg?branch=master)](http://codecov.io/github/47deg/fetch?branch=master) [![Maven Central](https://img.shields.io/badge/maven%20central-0.6.2-green.svg)](https://oss.sonatype.org/#nexus-search;gav~com.47deg~fetch*) [![License](https://img.shields.io/badge/license-Apache%202-blue.svg)](https://raw.githubusercontent.com/47deg/fetch/master/LICENSE) [![Latest version](https://img.shields.io/badge/fetch-0.6.2-green.svg)](https://index.scala-lang.org/47deg/fetch) [![Scala.js](http://scala-js.org/assets/badges/scalajs-0.6.15.svg)](http://scala-js.org) [![GitHub Issues](https://img.shields.io/github/issues/47deg/fetch.svg)](https://github.com/47deg/fetch/issues)

[comment]: # (End Badges)

Expand Down Expand Up @@ -106,7 +106,7 @@ Let's run it and wait for the fetch to complete:

```scala
fetchOne.runA[Id]
// [158] One ToString 1
// [913] One ToString 1
// res3: cats.Id[String] = 1
```

Expand All @@ -124,7 +124,7 @@ When executing the above fetch, note how the three identities get batched and th

```scala
fetchThree.runA[Id]
// [158] Many ToString NonEmptyList(3, 1, 2)
// [913] Many ToString NonEmptyList(3, 1, 2)
// res5: cats.Id[(String, String, String)] = (1,2,3)
```

Expand Down Expand Up @@ -165,8 +165,8 @@ Note how the two independent data fetches run in parallel, minimizing the latenc

```scala
fetchMulti.runA[Id]
// [159] One Length one
// [158] One ToString 1
// [914] One Length one
// [913] One ToString 1
// res7: cats.Id[(String, Int)] = (1,3)
```

Expand All @@ -185,9 +185,12 @@ While running it, notice that the data source is only queried once. The next tim

```scala
fetchTwice.runA[Id]
// [158] One ToString 1
// [913] One ToString 1
// res8: cats.Id[(String, String)] = (1,1)
```
## Fetch in the wild

If you wish to add your library here please consider a PR to include it in the list below.

[comment]: # (Start Copyright)
# Copyright
Expand All @@ -196,4 +199,4 @@ Fetch is designed and developed by 47 Degrees

Copyright (C) 2016-2017 47 Degrees. <http://47deg.com>

[comment]: # (End Copyright)
[comment]: # (End Copyright)
47 changes: 43 additions & 4 deletions project/ProjectPlugin.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import sbt.Keys._
import sbt._
import sbtorgpolicies.OrgPoliciesPlugin
import sbtorgpolicies.OrgPoliciesPlugin.autoImport._
import sbtorgpolicies.runnable.syntax._
import sbtorgpolicies.templates.badges._
import scoverage.ScoverageKeys
import tut.Plugin._

object ProjectPlugin extends AutoPlugin {
Expand Down Expand Up @@ -52,8 +54,8 @@ object ProjectPlugin extends AutoPlugin {
aggregate in doc := true)

lazy val readmeSettings: Seq[Def.Setting[_]] = tutSettings ++ commonTutSettings ++ Seq(
tutSourceDirectory := (baseDirectory in LocalRootProject).value,
tutTargetDirectory := (baseDirectory in LocalRootProject).value / "target",
tutSourceDirectory := (baseDirectory in LocalRootProject).value / "tut",
tutTargetDirectory := baseDirectory.value.getParentFile,
tutNameFilter := """README.md""".r
)

Expand All @@ -66,7 +68,24 @@ object ProjectPlugin extends AutoPlugin {
) ++ commonCrossDependencies
}

override def projectSettings: Seq[Def.Setting[_]] =
lazy val commandAliases: Seq[Def.Setting[_]] =
addCommandAlias("validate", ";clean;validateJS;validateJVM") ++
addCommandAlias("validateDocs", List("docs/tut", "readme/tut", "project root").asCmd) ++
addCommandAlias("validateCoverage", ";coverage;validate;coverageReport;coverageOff") ++
addCommandAlias("validateJVM", List(
"fetchJVM/compile",
"monixJVM/compile",
"fetchJVM/test",
"monixJVM/test",
"project root").asCmd) ++
addCommandAlias("validateJS", List(
"fetchJS/compile",
"monixJS/compile",
"fetchJS/test",
"monixJS/test",
"project root").asCmd)

override def projectSettings: Seq[Def.Setting[_]] = commandAliases ++
Seq(
description := "Simple & Efficient data access for Scala and Scala.js",
orgProjectName := "Fetch",
Expand All @@ -83,6 +102,11 @@ object ProjectPlugin extends AutoPlugin {
GitHubIssuesBadge.apply(_)
),
orgSupportedScalaJSVersion := Some("0.6.15"),
orgScriptTaskListSetting := List(
orgValidateFiles.asRunnableItem,
"validateDocs".asRunnableItemFull,
"validateCoverage".asRunnableItemFull
),
orgUpdateDocFilesSetting += baseDirectory.value / "tut",
scalaOrganization := "org.scala-lang",
scalaVersion := "2.12.2",
Expand All @@ -102,6 +126,21 @@ object ProjectPlugin extends AutoPlugin {
compilerPlugin(%%("paradise") cross CrossVersion.full) :: Nil
case _ =>
Nil
})
}),
ScoverageKeys.coverageFailOnMinimum := false
) ++ shellPromptSettings

implicit class CommandAliasOps(command: String) {

def asCmd: String =
if (command.contains("/")) s";project ${command.replaceAll("/", ";")}"
else s";$command"

}

implicit class CommandAliasListOps(commandList: List[String]) {

def asCmd: String = commandList.map(_.asCmd).mkString("")

}
}
3 changes: 2 additions & 1 deletion project/plugins.sbt
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
addSbtPlugin("com.47deg" % "sbt-org-policies" % "0.4.12")
resolvers += Resolver.sonatypeRepo("releases")
addSbtPlugin("com.47deg" % "sbt-org-policies" % "0.4.18")
202 changes: 202 additions & 0 deletions tut/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@

[comment]: # (Start Badges)

[![Join the chat at https://gitter.im/47deg/fetch](https://badges.gitter.im/47deg/fetch.svg)](https://gitter.im/47deg/fetch?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Build Status](https://travis-ci.org/47deg/fetch.svg?branch=master)](https://travis-ci.org/47deg/fetch) [![codecov.io](http://codecov.io/github/47deg/fetch/coverage.svg?branch=master)](http://codecov.io/github/47deg/fetch?branch=master) [![Maven Central](https://img.shields.io/badge/maven%20central-0.6.1-green.svg)](https://maven-badges.herokuapp.com/maven-central/com.47deg/fetch) [![License](https://img.shields.io/badge/license-Apache%202-blue.svg)](https://raw.githubusercontent.com/47deg/fetch/master/LICENSE) [![Latest version](https://index.scala-lang.org/47deg/fetch/fetch/latest.svg)](https://index.scala-lang.org/47deg/fetch/fetch) [![GitHub Issues](https://img.shields.io/github/issues/47deg/fetch.svg)](https://github.com/47deg/fetch/issues)

[comment]: # (End Badges)

# Fetch

A library for Simple & Efficient data access in Scala and Scala.js

- [Documentation](http://47deg.github.io/fetch/docs)

## Installation

Add the following dependency to your project's build file.

For Scala 2.11.x and 2.12.x:

[comment]: # (Start Replace)

```scala
"com.47deg" %% "fetch" % "0.6.1"
```

Or, if using Scala.js (0.6.x):

```scala
"com.47deg" %%% "fetch" % "0.6.1"
```

[comment]: # (End Replace)

```tut:invisible
val out = Console.out
def println(msg: String): Unit = {
Console.withOut(out) {
Console.println(msg)
}
}
```

## Remote data

Fetch is a library for making access to data both simple & efficient. Fetch is especially useful when querying data that
has a latency cost, such as databases or web services.

## Define your data sources

To tell `Fetch` how to get the data you want, you must implement the `DataSource` typeclass. Data sources have `fetchOne` and `fetchMany` methods that define how to fetch such a piece of data.

Data Sources take two type parameters:

1. `Identity` is a type that has enough information to fetch the data. For a users data source, this would be a user's unique ID.
2. `Result` is the type of data we want to fetch. For a users data source, this would the `User` type.

```scala
import cats.data.NonEmptyList

trait DataSource[Identity, Result]{
def name: String
def fetchOne(id: Identity): Query[Option[Result]]
def fetchMany(ids: NonEmptyList[Identity]): Query[Map[Identity, Result]]
}
```

We'll implement a dummy data source that can convert integers to strings. For convenience, we define a `fetchString` function that lifts identities (`Int` in our dummy data source) to a `Fetch`.

```tut:silent
import cats.data.NonEmptyList
import cats.instances.list._
import fetch._
implicit object ToStringSource extends DataSource[Int, String]{
override def name = "ToString"
override def fetchOne(id: Int): Query[Option[String]] = {
Query.sync({
println(s"[${Thread.currentThread.getId}] One ToString $id")
Option(id.toString)
})
}
override def fetchMany(ids: NonEmptyList[Int]): Query[Map[Int, String]] = {
Query.sync({
println(s"[${Thread.currentThread.getId}] Many ToString $ids")
ids.toList.map(i => (i, i.toString)).toMap
})
}
}
def fetchString(n: Int): Fetch[String] = Fetch(n) // or, more explicitly: Fetch(n)(ToStringSource)
```

## Creating and running a fetch

Now that we can convert `Int` values to `Fetch[String]`, let's try creating a fetch.

```tut:silent
import fetch.syntax._
val fetchOne: Fetch[String] = fetchString(1)
```

We'll run our fetches to the ambien `Id` monad in our examples. Note that in real-life scenarios you'll want to run a fetch to a concurrency monad such as `Future` or `Task`, synchronous execution of a fetch is only supported in Scala and not Scala.js and is meant for experimentation purposes.

```tut:silent
import cats.Id
import fetch.unsafe.implicits._
import fetch.syntax._
```

Let's run it and wait for the fetch to complete:

```tut:book
fetchOne.runA[Id]
```

## Batching

Multiple fetches to the same data source are automatically batched. For illustrating it, we are going to compose three independent fetch results as a tuple.

```tut:silent
import cats.syntax.cartesian._
val fetchThree: Fetch[(String, String, String)] = (fetchString(1) |@| fetchString(2) |@| fetchString(3)).tupled
```

When executing the above fetch, note how the three identities get batched and the data source is only queried once.

```tut:book
fetchThree.runA[Id]
```

## Parallelism

If we combine two independent fetches from different data sources, the fetches can be run in parallel. First, let's add a data source that fetches a string's size.

This time, instead of creating the results with `Query#sync` we are going to do it with `Query#async` for emulating an asynchronous data source.

```tut:silent
implicit object LengthSource extends DataSource[String, Int]{
override def name = "Length"
override def fetchOne(id: String): Query[Option[Int]] = {
Query.async((ok, fail) => {
println(s"[${Thread.currentThread.getId}] One Length $id")
ok(Option(id.size))
})
}
override def fetchMany(ids: NonEmptyList[String]): Query[Map[String, Int]] = {
Query.async((ok, fail) => {
println(s"[${Thread.currentThread.getId}] Many Length $ids")
ok(ids.toList.map(i => (i, i.size)).toMap)
})
}
}
def fetchLength(s: String): Fetch[Int] = Fetch(s)
```

And now we can easily receive data from the two sources in a single fetch.

```tut:silent
val fetchMulti: Fetch[(String, Int)] = (fetchString(1) |@| fetchLength("one")).tupled
```

Note how the two independent data fetches run in parallel, minimizing the latency cost of querying the two data sources.

```tut:book
fetchMulti.runA[Id]
```

## Caching

When fetching an identity, subsequent fetches for the same identity are cached. Let's try creating a fetch that asks for the same identity twice.

```tut:silent
val fetchTwice: Fetch[(String, String)] = for {
one <- fetchString(1)
two <- fetchString(1)
} yield (one, two)
```

While running it, notice that the data source is only queried once. The next time the identity is requested it's served from the cache.

```tut:book
fetchTwice.runA[Id]
```
## Fetch in the wild

If you wish to add your library here please consider a PR to include it in the list below.

[comment]: # (Start Copyright)

# Copyright

Fetch is designed and developed by 47 Degrees

Copyright (C) 2016-2017 47 Degrees. <http://47deg.com>

[comment]: # (End Copyright)

0 comments on commit b088bdc

Please sign in to comment.