{"id":16476248,"url":"https://github.com/softprops/ryu","last_synced_at":"2025-10-27T16:31:28.867Z","repository":{"id":823108,"uuid":"536939","full_name":"softprops/ryu","owner":"softprops","description":"A `Tornado Whirlwind Kick` scala client for the riak `raw` http interface","archived":false,"fork":false,"pushed_at":"2010-05-15T14:41:33.000Z","size":116,"stargazers_count":13,"open_issues_count":0,"forks_count":2,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-05-09T09:42:41.647Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Scala","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/softprops.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2010-02-26T06:57:12.000Z","updated_at":"2015-12-08T17:50:49.000Z","dependencies_parsed_at":"2022-07-15T03:46:49.981Z","dependency_job_id":null,"html_url":"https://github.com/softprops/ryu","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/softprops%2Fryu","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/softprops%2Fryu/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/softprops%2Fryu/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/softprops%2Fryu/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/softprops","download_url":"https://codeload.github.com/softprops/ryu/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":219861025,"owners_count":16556008,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-11T12:41:53.250Z","updated_at":"2025-10-27T16:31:23.416Z","avatar_url":"https://github.com/softprops.png","language":"Scala","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Ryu\n\nA `Tornado Whirlwind Kick` scala client for the [riak](http://riak.basho.com/) `raw` http interface\n\nRiak\n\n* is a distributed json document db\n* documents are stored in buckets\n* documents can be linked to other documents\n* queries come in 2 flavors\n  * `link walking`\n  * map/reduce\n\nScala\n\n* is awesome\n\n## fight\n\n### quick example\n\n    import ryu._\n    \n    val db = Ryu(\"localhost\", 8098)\n    \n    // store fighters\n    db(^('fighters, \"Ken\"), \"\"\"{\"fighting-style\":\"Shotokan\"}\"\"\")\n    db(^('fighters, \"Ryu\"), \"\"\"{\"fighting-style\":\"Shotokan\"}\"\"\")\n    db(^('fighters, \"Chun-Li\"), \"\"\"{\"fighting-style\":\"Chūgoku Kenpō\"}\"\"\")\n    \n    // now round up the fighters!\n    val (props, headers) = db(`fighters)\n    \n### baby steps\n\ndocuments have meta info which ryu uses as keys to access documents\n\n    val meta = ^('bucket, \"key\", Some(\"vclock\"), Some(\n      Seq(Link('bucket, Some(\"otherkey\"), \"linkTag\"))\n    ), \"application/json\")\n\nDid I just misspell 'clock'?\n\nNo. `vclocks` function similarly to the http `vtag` header in that they represent versions of documents. `Riak` uses these to avoid collisions.\n\na `bucket` is a container for yer data\n\na `key` is the key by which you refer to your value silly\n\na `vclock` is a unique hash of your document version\n\n`links` are a navigation utility used for traversing to other documents (think html anchors)\n\n`content type` is the type hint given to riak to store and retrive data\n\n`documents` have data (expected flavor is jsón)\n\n### more operations\n\n    import ryu._\n    \n    // ref riak\n    val db = Ryu(\"localhost\", 8098)\n    \n    // ref a key for sagat\n    val sagat = ^('fighters, \"sagat\")\n    \n    // create a link to sagat \n    val sagatLink = sagat asLink(\"boss\")\n    \n    // ref a key for dan\n    val dan = ^('fighters, \"dan\") + sagatLink\n    \n    // save or update sagat\n    db(sagat, \"\"\"{\"hp\":10}\"\"\")\n    \n    // save or update dan\n    db(dan, \"\"\"{\"hp\":100}\"\"\")\n    \n    // get dan\n    db(dan)\n    \n    // dan walks over to Sagat\n    db \u003e (dan, sagatLink.queryVal(true))\n  \n    // submit map reduce job to find all fighter hp's\n    db mapred(\n      Query(Seq((\"fighters\", None, None)), Seq(\n          Mapper named(\"Riak.mapValuesJson\") keep(false),\n          Reducer source(\"function(values){ var hps = []; values.forEach(function(v){ hps.push(v['hp']); }); return hps; }\"),\n      ))\n    )\n    \n    // delete (defeat) Sagat\n    db - sagat\n    \n    // validate m/r query\n    Query(Seq((\"fighters\", None, None)), Seq(\n        Linker tag(\"dan\")\n    )).validate // IllegalArgumentException (must contain a Mapper or Reducer)\n\n### A Ryu that doesn't have to block to win\n\nRyu also comes with an asynchronous interface for most ryu methods that accepts a callback for the response object.\n\n    // ! is for asynchonisity!\n    val db = Ryu(\"localhost\", 8098) ! \n\n    db(^('fighters, \"ken\"), \"punch later\") { ken =\u003e \n      println(ken._1) \n    }\n    println(\"kick\") \n    // \u003e kick\n    // \u003e punch later\n    \n\nThe asynchronous interfaces are `curry flavored` so you can bind the request to be handled later\n\n    val db = Ryu(\"localhost\", 8098) !\n    \n    val curriedPunch = db(^('fighters, \"ken\"), \"punch later\")_\n    \n    println(\"kick, kick, punch, kick\")\n    \n    // time to fight back!\n    curriedPunch { ken =\u003e\n      println(ken._1)\n    }\n\n## install\n\n* riak dependencies\n  * install [erlang](http://gist.github.com/302327)\n  * download and install [riak](http://downloads.basho.com/riak/) 0.9.1 or later\n\n* ryu\n  * TODO mvn repo\n\n## fork or knife ryu to fight back\n\ncontribute git://github.com/softprops/ryu.git\n\n## goals\n\n* provide a persisent k-v api with an interface akin to a Map\n* follow [dispatch](http://github.com/softprops/Databinder-Dispatch) idioms\n\n## todo\n\n* all methods return Option values `db(^('fighters, \"dan\")).getOrElse(default)`\n* extract Link objects when fetching documents\n* support multiple/arbitrary content types\n* document storage without a provided key\n* module for json \u003c-\u003e string conversions\n* use keep-alive for multi stage processing\n* finalize api\n\n## issues\n\nYou got issues with ryu? Take them up directly with him [here](http://github.com/softprops/ryu/issues).\n\n## references\n\n[riakka](http://github.com/timperrett/riakka) is another high kicking scala client for riaks `jiak` interface (Ryu bows to those that came before)\n \n[riak rest api](https://wiki.basho.com/display/RIAK/REST+API)\n\n[walking the link](http://blog.basho.com/2010/02/24/link-walking-by-example/)\n\n[riak map/reduce cartography](http://blog.basho.com/2010/02/03/the-release-riak-0.8-and-javascript-map/reduce/)\n\n[riak map/reduce video](http://vimeo.com/9188550)\n \n2010 Doug Tangren (softprops)","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsoftprops%2Fryu","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsoftprops%2Fryu","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsoftprops%2Fryu/lists"}