Skip to content

Commit 41d96b6

Browse files
Richard WhalingRichard Whaling
authored andcommitted
initial commit
1 parent e45a799 commit 41d96b6

File tree

14 files changed

+1586
-1
lines changed

14 files changed

+1586
-1
lines changed

README.md

Lines changed: 77 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,78 @@
11
# native-loop
2-
Extensible event loop and async-oriented IO for Scala Native; powered by libuv
2+
Extensible event loop and async-oriented IO for Scala Native; powered by libuv.
3+
4+
Shameless plug: code mostly adapted from my book, [Modern Systems Programming in Scala Native](https://pragprog.com/book/rwscala/modern-systems-programming-with-scala-native)
5+
6+
## What is it?
7+
native-loop provides a real, asynchronous ExecutionContext/Future implementation for Scala Native.
8+
It's backed by libuv, the same C library that the node.js ecosystem runs on; in addition to basic
9+
Future dispatching, we can also use libuv to provide other basic functionality, like:
10+
11+
- File IO
12+
- Pipe IO
13+
- TCP Sockets
14+
- UDP Sockets
15+
- Timers
16+
17+
To provide a working API for practical, async Scala Native programs, we have two subprojects,
18+
`client` and `server`, which provide an async HTTP client and server, respectively, by integrating addtional C libraries: [nodejs/http-parser](https://github.com/nodejs/http-parser) for request parsing, and [curl](https://github.com/curl/curl) for a full featured client with HTTPS support.
19+
20+
That said - providing a full-featured ecosystem in a single library isn't feasible - instead, we provide a `LoopExtension` trait that allows other C libaries to be integrated to the underlying event loop, in the same way that libcurl and http-parser are integrated; this opens up the possiblity of fully asynchronous bindings for postgres, redis, and many others.
21+
22+
## Why is this here?
23+
24+
To demonstrate the architectural style of a full, extensible async ecosystem for Scala Native, with an idiomatic Future-based API, implemented entirely as a library, and to start discussion about what we our priorities are.
25+
26+
## Maintenance Status
27+
28+
This code is a pre-release preview - I am cleaning up both the style and the implementation,
29+
aiming to align with Scala Native 0.4 for something more robust.
30+
31+
For now, I'm filing issues to remind myself of work that needs to be done.
32+
33+
I'll also create a few "discussion" issues for broader conversation.
34+
35+
Please feel free to file additional issues with questions, comments, and concerns!
36+
37+
## Server API Example
38+
39+
```
40+
def main(args:Array[String]):Unit = {
41+
Service()
42+
.getAsync("/async") { r => Future {
43+
s"got (async routed) request $r"
44+
}.map { message => OK(
45+
Map("asyncMessage" -> message)
46+
)
47+
}
48+
}
49+
.getAsync("/fetch/example") { r =>
50+
Curl.get(c"https://www.example.com").map { response =>
51+
Response(200,"OK",Map(),response.body)
52+
}
53+
}
54+
.get("/") { r => OK {
55+
Map("default_message" -> s"got (default routed) request $r")
56+
}
57+
}
58+
.run(9999)
59+
uv_run(EventLoop.loop, UV_RUN_DEFAULT)
60+
}
61+
```
62+
63+
## Streaming API Example
64+
65+
```
66+
def main(args:Array[String]):Unit = {
67+
val p = FilePipe(c"./data.txt")
68+
.map { d =>
69+
println(s"consumed $d")
70+
d
71+
}.addDestination(Tokenizer("\n"))
72+
.addDestination(Tokenizer(" "))
73+
.map { d => d + "\n" }
74+
.addDestination(FileOutputPipe(c"./output.txt", false))
75+
println("running")
76+
uv_run(EventLoop.loop,UV_RUN_DEFAULT)
77+
}
78+
```

build.sbt

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
lazy val commonSettings = Seq(
2+
organization := "dev.whaling",
3+
version := "preview",
4+
scalaVersion := "2.11.12",
5+
libraryDependencies += "io.argonaut" % "argonaut_native0.3_2.11" % "6.2.3"
6+
)
7+
8+
lazy val core = (project in file("core"))
9+
.settings(commonSettings:_*)
10+
.enablePlugins(ScalaNativePlugin)
11+
12+
lazy val pipe = (project in file("pipe"))
13+
.settings(commonSettings:_*)
14+
.enablePlugins(ScalaNativePlugin)
15+
.dependsOn(core)
16+
17+
lazy val client = (project in file("client"))
18+
.settings(commonSettings:_*)
19+
.enablePlugins(ScalaNativePlugin)
20+
.dependsOn(core)
21+
22+
lazy val server = (project in file("server"))
23+
.settings(commonSettings:_*)
24+
.enablePlugins(ScalaNativePlugin)
25+
.dependsOn(core)
26+
27+
lazy val serverExample = (project in file("server-example"))
28+
.settings(commonSettings:_*)
29+
.enablePlugins(ScalaNativePlugin)
30+
.dependsOn(core,server,client)
31+
32+
lazy val pipeExample = (project in file("pipe-example"))
33+
.settings(commonSettings:_*)
34+
.enablePlugins(ScalaNativePlugin)
35+
.dependsOn(core,pipe,client)

0 commit comments

Comments
 (0)