diff --git a/lib/template/Gemfile b/lib/template/Gemfile index 6bc316d..50269f5 100644 --- a/lib/template/Gemfile +++ b/lib/template/Gemfile @@ -1,7 +1,8 @@ +# use "bundle install" to update gems; "gem install bundler" to install bundler. source :rubygems source "http://gems.local.twitter.com" -gem "thrift_client", "0.6" -gem "thrift", "0.5" +gem "thrift_client", "0.6.2" +gem "thrift", "0.6" gem "railsless-deploy" gem "capistrano" gem "twitter-cap-utils", "~>0.8.0" diff --git a/lib/template/README.md b/lib/template/README.md index 3ef1411..7b94740 100644 --- a/lib/template/README.md +++ b/lib/template/README.md @@ -8,6 +8,16 @@ properly, you may want to: There is a tutorial for what to do next, which you can find in the scala-bootstrapper README.rdoc file. +# Configuring Intellij + +If you want to setup Intellij, it has to happen off to the side: + + $ sbt + > *sbtIdeaRepo at http://mpeltonen.github.com/maven/ + > *idea is com.github.mpeltonen sbt-idea-processor 0.4.0 + > update + > idea + # Documenting your project Add documentation here! Eventually, you'll be able to publish this to diff --git a/lib/template/TUTORIAL.md b/lib/template/TUTORIAL.md index f5d71bd..ffb5313 100644 --- a/lib/template/TUTORIAL.md +++ b/lib/template/TUTORIAL.md @@ -21,47 +21,72 @@ or you can ask sbt to run your service: $ sbt 'run -f config/development.scala' +### Verify that the service is running + +The java/sbt command-lines will "hang" because the server is running in the +foreground. (In production, we use libslack-daemon to wrap java processes into +unix daemons.) Go to another terminal and check for a logfile. If your server +is named "birdname", there should be a `birdname.log` with contents like this: + + INF [20110615-14:05:41.656] stats: Starting JsonStatsLogger + INF [20110615-14:05:41.674] admin: Starting TimeSeriesCollector + DEB [20110615-14:05:41.792] nio: Using the autodetected NIO constraint level: 0 + +That's your indication that the server is running. :) + ### View the Thrift IDL for your service -The IDL for your service is in src/main/thrift/birdname.thrift. The +The IDL for your service is in `src/main/thrift/birdname.thrift`. The Thrift compiler uses the IDL to generate bindings for various languages, making it easy for scripts in those languages to talk to your service. More information about Thrift and how to write an IDL -for your service can be found [here](http://wiki.apache.org/thrift/Tutorial) +for your service can be found [here](http://wiki.apache.org/thrift/Tutorial). ### Call your service from ruby Your service implements simple get() and put() methods. Once you have your server running, as above, bring up a different shell and: - $ bundle install $ cd birdname - $ ./src/scripts/console - $ $client - $ $client.put("key1", "valueForKey") - $ $client.get("key1") + $ bundle install + $ ./dist/birdname/scripts/console + >> $client + >> $client.put("key1", "valueForKey") + >> $client.get("key1") ### Look at the stats for your service By default, your project is configured to use [Ostrich](https://github.com/twitter/ostrich), a library for service -configuration, administration, and stats reporting. Your config file -in config/development.scala defines which port ostrich uses for admin -requests. You can view the stats via that port: +configuration, administration, and stats reporting. Your config file +in `config/development.scala` defines which port ostrich uses for admin +requests. You can view the stats via that port: $ curl localhost:9900/stats.txt counters: - Nho2/connects: 1 - Nho2/requests: 2 - Nho2/success: 2 + BirdName/connects: 1 + BirdName/requests: 2 + BirdName/success: 2 ... Ostrich also stores historial stats data and can build [graphs](http://localhost:9900/graph/) for you. +### Stop the service + +You can ask the server to shutdown over the admin port also: + + $ curl localhost:9900/shutdown.txt + ok + ### View the implementation of get() and put() -Take a look at src/main/scala/com/twitter/birdname/BirdNameServiceImpl.scala. +In `src/main/scala`, take a look at `BirdNameServiceImpl.scala`. (This may +have a different name, based on what you called your server.) + +The base interface is specified by thrift. Additionally, we're using Twitter's +async I/O framework: finagle. Finagle (and a lot of great documentation about +it) is hosted here: https://github.com/twitter/finagle ### Try adding some timers and counters @@ -102,7 +127,7 @@ example: framework that allows you to write semi-human-readable descriptions of how your service should behave and test that those descriptions are valid. You already have some Specs code for your project in -src/test/scala/com/twitter/birdname/BirdNameServiceImpl.scala. Check +src/test/scala/com/twitter/birdname/BirdNameServiceSpec.scala. Check out the existing test and add a new one for the counter functionality we just added. diff --git a/lib/template/project/build/BirdNameProject.scala.erb b/lib/template/project/build/BirdNameProject.scala.erb index e2c5cbd..4751579 100644 --- a/lib/template/project/build/BirdNameProject.scala.erb +++ b/lib/template/project/build/BirdNameProject.scala.erb @@ -28,7 +28,7 @@ class BirdNameProject(info: ProjectInfo) extends StandardServiceProject(info) val util = "com.twitter" % "util" % "1.8.3" override def originalThriftNamespaces = Map("BirdName" -> "com.twitter.birdname.thrift") - val scalaThriftTargetNamespace = "com.twitter.birdname" + override val scalaThriftTargetNamespace = "com.twitter.birdname" val slf4jVersion = "1.5.11" val slf4jApi = "org.slf4j" % "slf4j-api" % slf4jVersion withSources() intransitive() diff --git a/lib/template/project/plugins/Plugins.scala.erb b/lib/template/project/plugins/Plugins.scala.erb index 36e58ed..6b33855 100644 --- a/lib/template/project/plugins/Plugins.scala.erb +++ b/lib/template/project/plugins/Plugins.scala.erb @@ -11,10 +11,14 @@ class Plugins(info: ProjectInfo) extends PluginDefinition(info) { } else if (isSBTTwitter) { Set("twitter.artifactory" at "http://artifactory.local.twitter.com/repo/") } else { - super.repositories ++ Seq("twitter.com" at "http://maven.twttr.com/") + super.repositories ++ Set( + "twitter.com" at "http://maven.twttr.com/", + "scala-tools" at "http://scala-tools.org/repo-releases/", + "freemarker" at "http://freemarker.sourceforge.net/maven2/" + ) } override def ivyRepositories = Seq(Resolver.defaultLocal(None)) ++ repositories - val standardProject = "com.twitter" % "standard-project" % "0.11.16" - val sbtThrift = "com.twitter" % "sbt-thrift" % "1.3.11" + val standardProject = "com.twitter" % "standard-project" % "0.12.7" + val sbtThrift = "com.twitter" % "sbt-thrift" % "1.4.4" } diff --git a/lib/template/src/scripts/startup.sh b/lib/template/src/scripts/startup.sh index c3bb0b8..5d81cb7 100644 --- a/lib/template/src/scripts/startup.sh +++ b/lib/template/src/scripts/startup.sh @@ -18,7 +18,7 @@ STAGE="production" HEAP_OPTS="-Xmx4096m -Xms4096m -XX:NewSize=768m" GC_OPTS="-XX:+UseParallelOldGC -XX:+UseAdaptiveSizePolicy -XX:MaxGCPauseMillis=1000 -XX:GCTimeRatio=99" -GC_LOG_OPTS="-verbosegc -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -XX:+PrintTenuringDistribution -XX:+PrintHeapAtGC" +GC_LOG_OPTS="-XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -XX:+PrintTenuringDistribution -XX:+PrintHeapAtGC" GC_LOG="-Xloggc:/var/log/$APP_NAME/gc.log" DEBUG_OPTS="-XX:ErrorFile=/var/log/$APP_NAME/java_error%p.log" JAVA_OPTS="-server -Dstage=$STAGE $GC_OPTS $GC_LOG_OPTS $GC_LOG $HEAP_OPTS $DEBUG_OPTS"