Skip to content

Commit fa076ef

Browse files
committed
Merge branch 'release-0.1.0'
2 parents 1d275dd + 15c92e7 commit fa076ef

File tree

17 files changed

+1491
-0
lines changed

17 files changed

+1491
-0
lines changed

README.md

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,47 @@
11
# Redis Algebra
2+
3+
A Redis library for Scala that is built on Scalaz's free monad implementation, designed in the spirit of Swierstra's [Data types a la carte](http://www.staff.science.uu.nl/~swier004/Publications/DataTypesALaCarte.pdf). The library is intended to be used in combination with other free monad based libraries to build rich algebras tailored to the user's needs.
4+
5+
The functions that this library provides correspond to the list of [Redis commands](http://redis.io/commands). In order to run programs that have been written using this library, an interpreter needs to be implemented to handle each of the commands. There is no interpreter included by default; however, one may be made available in a separate repository. Interpreters may be interchanged freely based on the user's desired behaviour. For instance, a non-blocking interpreter that sends commands to Redis may be used in production, while an interpreter that uses an in-memory representation may be used when running tests.
6+
7+
# Install
8+
9+
Releases and snapshots of the Redis Algebra library are published to the [Sonatype OSS Repository Hosting Service](https://oss.sonatype.org). The necessary [SBT Resolvers](http://www.scala-sbt.org/release/docs/Detailed-Topics/Resolvers.html) may be added as follows to your SBT build file.
10+
11+
```scala
12+
resolvers += "Sonatype releases" at "http://oss.sonatype.org/content/repositories/releases/"
13+
14+
resolvers += "Sonatype snapshots" at "http://oss.sonatype.org/content/repositories/snapshots/"
15+
```
16+
17+
# Usage
18+
19+
```scala
20+
import scala.language.implicitConversions
21+
import scalaz.{CharSet, NonEmptyList}, NonEmptyList.nels
22+
import scalaz.std.list._
23+
import scalaz.syntax.{Ops, monad, traverse}, monad._, traverse._
24+
25+
import redis.algebra.{F, R}
26+
import redis.algebra.all._
27+
28+
val e0 =
29+
set[R]("key".utf8, "value".utf8) >>
30+
get[R]("key".utf8)
31+
32+
val e1 =
33+
set[R]("counter".utf8, 100L.utf8) >>
34+
incr[R]("counter".utf8) >>
35+
incr[R]("counter".utf8) >>
36+
incrby[R]("counter".utf8, 10L)
37+
38+
val e2 =
39+
List("first".utf8, "second".utf8, "third".utf8).map(a => rpush[R]("messages".utf8, nels(a))).sequenceU >>
40+
lrange[R]("messages".utf8, 0, 2)
41+
42+
implicit def StringToStringOps(a: String): StringOps = new StringOps { val self = a }
43+
44+
implicit def LongToStringOps(a: Long): StringOps = new StringOps { val self = a.toString }
45+
46+
sealed abstract class StringOps extends Ops[String] { final def utf8 = self.getBytes(CharSet.UTF8).toIndexedSeq }
47+
```

build.sbt

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
organization := "com.github.ethul"
2+
3+
name := "redis-algebra"
4+
5+
version := "0.1.0"
6+
7+
scalaVersion := "2.10.4"
8+
9+
libraryDependencies += "org.scalaz" %% "scalaz-core" % "7.1.0-M7"
10+
11+
libraryDependencies += "org.specs2" %% "specs2" % "2.2.2-scalaz-7.1.0-M3" % "test"
12+
13+
resolvers += "Sonatype releases" at "https://oss.sonatype.org/content/repositories/releases/"
14+
15+
resolvers += "Sonatype snapshots" at "https://oss.sonatype.org/content/repositories/snapshots/"
16+
17+
scalacOptions += "-feature"
18+
19+
scalacOptions += "-deprecation"
20+
21+
scalacOptions += "-unchecked"
22+
23+
scalacOptions += "-language:higherKinds"
24+
25+
scalacOptions += "-Xlint"
26+
27+
scalacOptions += "-Xfatal-warnings"
28+
29+
scalacOptions += "-Yno-adapted-args"
30+
31+
scalacOptions += "-Ywarn-all"
32+
33+
publishTo <<= version.apply { v =>
34+
val nexus = "https://oss.sonatype.org/"
35+
if (v.trim.endsWith("SNAPSHOT"))
36+
Some("Snapshots" at nexus + "content/repositories/snapshots")
37+
else
38+
Some("Releases" at nexus + "service/local/staging/deploy/maven2")
39+
}
40+
41+
credentials += Credentials(Path.userHome / ".ivy2" / ".credentials")
42+
43+
pomIncludeRepository := Function.const(false)
44+
45+
pomExtra :=
46+
<licenses>
47+
<license>
48+
<name>MIT</name>
49+
<url>http://www.opensource.org/licenses/mit-license.php</url>
50+
<distribution>repo</distribution>
51+
</license>
52+
</licenses>
53+
<scm>
54+
<url>https://github.com/ethul/redis-algebra</url>
55+
<connection>scm:git:git@github.com:ethul/redis-algebra.git</connection>
56+
<developerConnection>scm:git:git@github.com:ethul/redis-algebra.git</developerConnection>
57+
</scm>
58+
<developers>
59+
<developer>
60+
<id>ethul</id>
61+
<name>Eric Thul</name>
62+
<url>https://github.com/ethul</url>
63+
</developer>
64+
</developers>

project/build.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
sbt.version=0.13.5
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package redis
2+
package algebra
3+
4+
import scalaz.{Free, Functor, Inject, InjectFunctions}, Free.Return
5+
6+
import data.Status
7+
8+
sealed abstract class ConnectionAlgebra[A]
9+
10+
final case class Auth[A](password: ByteString, h: Status => A) extends ConnectionAlgebra[A]
11+
12+
final case class Echo[A](message: ByteString, h: ByteString => A) extends ConnectionAlgebra[A]
13+
14+
final case class Ping[A](h: Status => A) extends ConnectionAlgebra[A]
15+
16+
final case class Quit[A](h: Status => A) extends ConnectionAlgebra[A]
17+
18+
final case class Select[A](index: Short, h: Status => A) extends ConnectionAlgebra[A]
19+
20+
trait ConnectionInstances {
21+
implicit val connectionAlgebraFunctor: Functor[ConnectionAlgebra] =
22+
new Functor[ConnectionAlgebra] {
23+
def map[A, B](a: ConnectionAlgebra[A])(f: A => B): ConnectionAlgebra[B] =
24+
a match {
25+
case Auth(p, h) => Auth(p, x => f(h(x)))
26+
case Echo(m, h) => Echo(m, x => f(h(x)))
27+
case Ping(h) => Ping(x => f(h(x)))
28+
case Quit(h) => Quit(x => f(h(x)))
29+
case Select(i, h) => Select(i, x => f(h(x)))
30+
}
31+
}
32+
}
33+
34+
trait ConnectionFunctions extends InjectFunctions {
35+
def auth[F[_]: Functor](password: ByteString)(implicit I: Inject[ConnectionAlgebra, F]): Free[F, Status] =
36+
inject[F, ConnectionAlgebra, Status](Auth(password, Return(_)))
37+
38+
def echo[F[_]: Functor](message: ByteString)(implicit I: Inject[ConnectionAlgebra, F]): Free[F, ByteString] =
39+
inject[F, ConnectionAlgebra, ByteString](Echo(message, Return(_)))
40+
41+
def ping[F[_]: Functor](implicit I: Inject[ConnectionAlgebra, F]): Free[F, Status] =
42+
inject[F, ConnectionAlgebra, Status](Ping(Return(_)))
43+
44+
def quit[F[_]: Functor](implicit I: Inject[ConnectionAlgebra, F]): Free[F, Status] =
45+
inject[F, ConnectionAlgebra, Status](Quit(Return(_)))
46+
47+
def select[F[_]: Functor](index: Short)(implicit I: Inject[ConnectionAlgebra, F]): Free[F, Status] =
48+
inject[F, ConnectionAlgebra, Status](Select(index, Return(_)))
49+
}
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
package redis
2+
package algebra
3+
package data
4+
5+
import scalaz.NonEmptyList
6+
7+
sealed abstract class Status
8+
case object Ok extends Status
9+
case object Error extends Status
10+
case object Wrongtype extends Status
11+
12+
sealed abstract class Type
13+
case object String extends Type
14+
case object List extends Type
15+
case object Set extends Type
16+
case object ZSet extends Type
17+
case object Hash extends Type
18+
19+
sealed abstract class ObjectSubcommand
20+
final case class Refcount(key: ByteString) extends ObjectSubcommand
21+
final case class Encoding(key: ByteString) extends ObjectSubcommand
22+
final case class Idletime(key: ByteString) extends ObjectSubcommand
23+
24+
sealed abstract class ObjectResult
25+
final case class RefcountResult(value: Long) extends ObjectResult
26+
final case class EncodingResult(value: ByteString) extends ObjectResult
27+
final case class IdletimeResult(value: Long) extends ObjectResult
28+
29+
sealed abstract class LuaResult
30+
final case class LuaNumber(value: Long) extends LuaResult
31+
final case class LuaString(value: ByteString) extends LuaResult
32+
final case class LuaTable(value: Seq[ByteString]) extends LuaResult
33+
final case class LuaStatus(value: Status) extends LuaResult
34+
final case class LuaBoolean(value: Boolean) extends LuaResult
35+
36+
sealed abstract class Master
37+
final case class Host(name: ByteString, port: Int) extends Master
38+
case object Noone extends Master
39+
40+
sealed abstract class SlowlogSubcommand
41+
final case class Get(limit: Option[Int] = None) extends SlowlogSubcommand
42+
case object Len extends SlowlogSubcommand
43+
case object Reset extends SlowlogSubcommand
44+
45+
sealed abstract class SlowlogResult
46+
final case class GetResult(value: Seq[ByteString]) extends SlowlogResult
47+
final case class LenResult(value: Int) extends SlowlogResult
48+
case object ResetResult extends SlowlogResult
49+
50+
sealed abstract class BitOperation
51+
final case class And(dest: ByteString, keys: NonEmptyList[ByteString]) extends BitOperation
52+
final case class Or(dest: ByteString, keys: NonEmptyList[ByteString]) extends BitOperation
53+
final case class Xor(dest: ByteString, keys: NonEmptyList[ByteString]) extends BitOperation
54+
final case class Not(dest: ByteString, key: ByteString) extends BitOperation
55+
56+
sealed abstract class SetOption
57+
case object Nx extends SetOption
58+
case object Xx extends SetOption
59+
60+
sealed abstract class Endpoint
61+
final case class Closed(value: Double) extends Endpoint
62+
final case class Open(value: Double) extends Endpoint
63+
case object -∞ extends Endpoint
64+
case object +∞ extends Endpoint
65+
66+
sealed abstract class Aggregate
67+
case object Sum extends Aggregate
68+
case object Min extends Aggregate
69+
case object Max extends Aggregate
70+
71+
sealed abstract class Order
72+
case object Asc extends Order
73+
case object Desc extends Order
74+
75+
sealed abstract class Position
76+
case object Before extends Position
77+
case object After extends Position
78+
79+
sealed abstract class By
80+
case object Nosort extends By
81+
final case class Pattern(pattern: ByteString) extends By
82+
83+
final case class Limit(offset: Long, count: Long)
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
package redis
2+
package algebra
3+
4+
import scalaz.{Free, Functor, Inject, InjectFunctions, NonEmptyList}, Free.Return
5+
6+
import data.Status
7+
8+
sealed abstract class HashAlgebra[A]
9+
10+
final case class Hdel[A](key: ByteString, fields: NonEmptyList[ByteString], h: Long => A) extends HashAlgebra[A]
11+
12+
final case class Hexists[A](key: ByteString, field: ByteString, h: Boolean => A) extends HashAlgebra[A]
13+
14+
final case class Hget[A](key: ByteString, field: ByteString, h: Option[ByteString] => A) extends HashAlgebra[A]
15+
16+
final case class Hgetall[A](key: ByteString, h: Seq[(ByteString, ByteString)] => A) extends HashAlgebra[A]
17+
18+
final case class Hincrby[A](key: ByteString, field: ByteString, increment: Long, h: Long => A) extends HashAlgebra[A]
19+
20+
final case class Hincrbyfloat[A](key: ByteString, field: ByteString, increment: BigDecimal, h: BigDecimal => A) extends HashAlgebra[A]
21+
22+
final case class Hkeys[A](key: ByteString, h: Seq[ByteString] => A) extends HashAlgebra[A]
23+
24+
final case class Hlen[A](key: ByteString, h: Long => A) extends HashAlgebra[A]
25+
26+
final case class Hmget[A](key: ByteString, fields: NonEmptyList[ByteString], h: Seq[Option[ByteString]] => A) extends HashAlgebra[A]
27+
28+
final case class Hmset[A](key: ByteString, pairs: NonEmptyList[(ByteString, ByteString)], h: Status => A) extends HashAlgebra[A]
29+
30+
final case class Hset[A](key: ByteString, field: ByteString, value: ByteString, h: Boolean => A) extends HashAlgebra[A]
31+
32+
final case class Hsetnx[A](key: ByteString, field: ByteString, value: ByteString, h: Boolean => A) extends HashAlgebra[A]
33+
34+
final case class Hvals[A](key: ByteString, h: Seq[ByteString] => A) extends HashAlgebra[A]
35+
36+
trait HashInstances {
37+
implicit val hashAlgebraFunctor: Functor[HashAlgebra] =
38+
new Functor[HashAlgebra] {
39+
def map[A, B](a: HashAlgebra[A])(f: A => B): HashAlgebra[B] =
40+
a match {
41+
case Hdel(k, s, h) => Hdel(k, s, x => f(h(x)))
42+
case Hexists(k, s, h) => Hexists(k, s, x => f(h(x)))
43+
case Hget(k, s, h) => Hget(k, s, x => f(h(x)))
44+
case Hgetall(k, h) => Hgetall(k, x => f(h(x)))
45+
case Hincrby(k, s, i, h) => Hincrby(k, s, i, x => f(h(x)))
46+
case Hincrbyfloat(k, s, i, h) => Hincrbyfloat(k, s, i, x => f(h(x)))
47+
case Hkeys(k, h) => Hkeys(k, x => f(h(x)))
48+
case Hlen(k, h) => Hlen(k, x => f(h(x)))
49+
case Hmget(k, s, h) => Hmget(k, s, x => f(h(x)))
50+
case Hmset(k, p, h) => Hmset(k, p, x => f(h(x)))
51+
case Hset(k, s, v, h) => Hset(k, s, v, x => f(h(x)))
52+
case Hsetnx(k, s, v, h) => Hsetnx(k, s, v, x => f(h(x)))
53+
case Hvals(k, h) => Hvals(k, x => f(h(x)))
54+
}
55+
}
56+
}
57+
58+
trait HashFunctions extends InjectFunctions {
59+
def hdel[F[_]: Functor](key: ByteString, fields: NonEmptyList[ByteString])(implicit I: Inject[HashAlgebra, F]): Free[F, Long] =
60+
inject[F, HashAlgebra, Long](Hdel(key, fields, Return(_)))
61+
62+
def hexists[F[_]: Functor](key: ByteString, field: ByteString)(implicit I: Inject[HashAlgebra, F]): Free[F, Boolean] =
63+
inject[F, HashAlgebra, Boolean](Hexists(key, field, Return(_)))
64+
65+
def hget[F[_]: Functor](key: ByteString, field: ByteString)(implicit I: Inject[HashAlgebra, F]): Free[F, Option[ByteString]] =
66+
inject[F, HashAlgebra, Option[ByteString]](Hget(key, field, Return(_)))
67+
68+
def hgetall[F[_]: Functor](key: ByteString)(implicit I: Inject[HashAlgebra, F]): Free[F, Seq[(ByteString, ByteString)]] =
69+
inject[F, HashAlgebra, Seq[(ByteString, ByteString)]](Hgetall(key, Return(_)))
70+
71+
def hincrby[F[_]: Functor](key: ByteString, field: ByteString, increment: Long)(implicit I: Inject[HashAlgebra, F]): Free[F, Long] =
72+
inject[F, HashAlgebra, Long](Hincrby(key, field, increment, Return(_)))
73+
74+
def hincrbyfloat[F[_]: Functor](key: ByteString, field: ByteString, increment: BigDecimal)(implicit I: Inject[HashAlgebra, F]): Free[F, BigDecimal] =
75+
inject[F, HashAlgebra, BigDecimal](Hincrbyfloat(key, field, increment, Return(_)))
76+
77+
def hkeys[F[_]: Functor](key: ByteString)(implicit I: Inject[HashAlgebra, F]): Free[F, Seq[ByteString]] =
78+
inject[F, HashAlgebra, Seq[ByteString]](Hkeys(key, Return(_)))
79+
80+
def hlen[F[_]: Functor](key: ByteString)(implicit I: Inject[HashAlgebra, F]): Free[F, Long] =
81+
inject[F, HashAlgebra, Long](Hlen(key, Return(_)))
82+
83+
def hmget[F[_]: Functor](key: ByteString, fields: NonEmptyList[ByteString])(implicit I: Inject[HashAlgebra, F]): Free[F, Seq[Option[ByteString]]] =
84+
inject[F, HashAlgebra, Seq[Option[ByteString]]](Hmget(key, fields, Return(_)))
85+
86+
def hmset[F[_]: Functor](key: ByteString, pairs: NonEmptyList[(ByteString, ByteString)])(implicit I: Inject[HashAlgebra, F]): Free[F, Status] =
87+
inject[F, HashAlgebra, Status](Hmset(key, pairs, Return(_)))
88+
89+
def hset[F[_]: Functor](key: ByteString, field: ByteString, value: ByteString)(implicit I: Inject[HashAlgebra, F]): Free[F, Boolean] =
90+
inject[F, HashAlgebra, Boolean](Hset(key, field, value, Return(_)))
91+
92+
def hsetnx[F[_]: Functor](key: ByteString, field: ByteString, value: ByteString)(implicit I: Inject[HashAlgebra, F]): Free[F, Boolean] =
93+
inject[F, HashAlgebra, Boolean](Hsetnx(key, field, value, Return(_)))
94+
95+
def hvals[F[_]: Functor](key: ByteString)(implicit I: Inject[HashAlgebra, F]): Free[F, Seq[ByteString]] =
96+
inject[F, HashAlgebra, Seq[ByteString]](Hvals(key, Return(_)))
97+
}

0 commit comments

Comments
 (0)