Skip to content
This repository has been archived by the owner on Mar 11, 2020. It is now read-only.

Doc fixes #99

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions docs/src/main/tut/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,10 +89,9 @@ The structure breaks down like this:
Once you have the layout configured, using remotely is just like using any other library within SBT; simply add the dependency to your `rpc-protocol` module:

```
resolvers += "Remotely Bintray Repo" at "http://dl.bintray.com/oncue/releases"

libraryDependencies += "oncue" %% "remotely-core" % "x.x.+"

resolvers += Resolver.bintrayRepo("oncue", "releases")

libraryDependencies += "oncue.remotely" %% "core" % "x.x.+"
```

### Protocol Definition
Expand All @@ -105,7 +104,7 @@ import remotely._, codecs._
object protocol {
val definition = Protocol.empty
.codec[Int]
.specify1[Int, Int]("factorial")
.specify1("factorial", Field.strict[Int]("n"), Type[Int])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI, if you wish to get the old behavior you can use this:

import remotely._
import Field._
import shapeless.HList
import shapeless.ops.hlist.{Selector, Prepend}
import scala.reflect.runtime.universe.TypeTag
import scalaz.\/
import scalaz.syntax.either._

object protocol {

  /// Convenience Syntax

  implicit class ProtocolOps[I <: HList](inner: Protocol[I]) {

    def ++[O <: HList](other: Protocol[O])(implicit p : Prepend[I, O]): Protocol[p.Out] = {
      val c: Codecs[p.Out] = inner.codecs ++ other.codecs
      val s = Signatures(inner.signatures.signatures ++ other.signatures.signatures)
      Protocol(c, s)
    }

    def define0[O:TypeTag](name: String)
      (implicit SO : Selector[I, O]): Protocol[I] = inner.specify0(name, Type[O])

    def define1[A:TypeTag,O:TypeTag](name: String)
      (implicit SA : Selector[I, A], SO : Selector[I, O]): Protocol[I] = {

      val f1 = strict[A]("in1")

      inner.specify1(name, f1, Type[O])
    }

    def define2[A:TypeTag,B:TypeTag,O:TypeTag](name: String)
      (implicit SA : Selector[I, A], SB : Selector[I, B],
                SO : Selector[I, O]): Protocol[I] = {

      val f1 = strict[A]("in1")
      val f2 = strict[B]("in2")

      inner.specify2(name, f1, f2, Type[O])
    }

    def define3[A:TypeTag,B:TypeTag,C:TypeTag,O:TypeTag](name: String)
      (implicit SA : Selector[I, A], SB : Selector[I, B],
                SC : Selector[I, C], SO : Selector[I, O]): Protocol[I] = {

      val f1 = strict[A]("in1")
      val f2 = strict[B]("in2")
      val f3 = strict[C]("in3")

      inner.specify3(name, f1, f2, f3, Type[O])
    }

    def define4[A:TypeTag,B:TypeTag,C:TypeTag,D:TypeTag,O:TypeTag](name: String)
      (implicit SA : Selector[I, A], SB : Selector[I, B],
                SC : Selector[I, C], SD : Selector[I, D],
                SO : Selector[I, O]): Protocol[I] = {

      val f1 = strict[A]("in1")
      val f2 = strict[B]("in2")
      val f3 = strict[C]("in3")
      val f4 = strict[D]("in4")

      inner.specify4(name, f1, f2, f3, f4, Type[O])
    }

  }
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, didn't notice that, thanks :)
Which form would you encourage for new users? That's what should go into the docs, I suppose :)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@timperrett I think the new DSL is a bit unfriendly compared to what we had. Perhaps we should add the convenience syntax above to the core library and document differences. However, this makes little sense if the plan is to introduce some higher level DSL that is even more friendly to use.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Which form would you encourage for new users? That's what should go into the docs, I suppose :)

I did that ProtocolOps because I dislike the boilerplate introduced by Field and Type. I understand the rationale behind the types, but not so much in a DSL.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah I see :) specify1 stays there for now then

}

```
Expand Down Expand Up @@ -144,11 +143,12 @@ class FactorialServer0 extends FactorialServer {
val factorial: Int => Response[Int] = n =>
Response.now { (1 to n).product }
}

```

The `GenServer` macro does require all the FQCN of all the inputs, so here we must use `oncue.svc.example.protocol.definition`. For example, using just `protocol.definition` after `import oncue.svc.example._` would *not* work, as in that case, the macro would then only see the AST: `protocol.definition` which doesn't have a value in the compiler context, but provided you organize your project in the manner described earlier in this document.

The macro generates abstract method definitions (as specified in the protocol), and also adds an `environment: Environment`, member to the class, which contains all codecs and values (a value is a reference to a specific method implementation).

In a similar fashion, clients are also very simple. The difference here is that clients are fully complete, and do not require any implementation as the function arguments defined in the protocol are entirely known at compile time.

```
Expand Down Expand Up @@ -201,7 +201,7 @@ This is super straightforward, but lets step through the values one by one.

* `service`: An instance of the server implementation (which in turn implements the macro-generated interface based on the protocol)

* `env`: For any given service implementation, an `Environment` can be derived from it. Unlike the protocol implementation itself, `Environment` is a concrete thing that can be bound and executed at runtime, where as `Protocol` is primarily a compile-time artifact.
* `environment`: For any given service implementation, an `Environment` can be derived from it. Unlike the protocol implementation itself, `Environment` is a concrete thing that can be bound and executed at runtime, where as `Protocol` is primarily a compile-time artifact.

* `startServer`: Calling `env.serve(...)` returns A Task that when run will start the server, binding the process to the specified address.

Expand Down