{"id":32184861,"url":"https://github.com/yetanalytics/kria","last_synced_at":"2025-10-21T23:58:47.645Z","repository":{"id":57713590,"uuid":"51452957","full_name":"yetanalytics/kria","owner":"yetanalytics","description":"Riak 2.0 asynchronous Clojure client. Written with callback functions; requires Java 7 because it uses NIO.2.","archived":false,"fork":true,"pushed_at":"2016-03-01T16:51:59.000Z","size":358,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-10-21T23:58:44.224Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Clojure","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"bluemont/kria","license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/yetanalytics.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-02-10T16:15:23.000Z","updated_at":"2016-02-10T16:15:24.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/yetanalytics/kria","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/yetanalytics/kria","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yetanalytics%2Fkria","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yetanalytics%2Fkria/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yetanalytics%2Fkria/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yetanalytics%2Fkria/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/yetanalytics","download_url":"https://codeload.github.com/yetanalytics/kria/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yetanalytics%2Fkria/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":280354183,"owners_count":26316401,"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","status":"online","status_checked_at":"2025-10-21T02:00:06.614Z","response_time":58,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":"2025-10-21T23:58:41.744Z","updated_at":"2025-10-21T23:58:47.634Z","avatar_url":"https://github.com/yetanalytics.png","language":"Clojure","funding_links":[],"categories":[],"sub_categories":[],"readme":"# kria\n\nAn asynchronous Clojure client for Riak 2.0 built on top of the [Riak Protocol\nBuffer interface][Riak-PB] using Java 7's NIO.2.\n\nKria only only has four dependencies:\n\n* Java 7 or later (for NIO.2)\n* Clojure 1.6\n* Protocol Buffers\n* [Basho's Riak Protocol Buffer Files][riak-pb-maven]\n\n[riak-pb-maven]: https://search.maven.org/#search%7Cga%7C1%7Ca%3A%22riak-pb%22\n\nI intentionally avoided Netty to reduce complexity. At present, Kria has about\n2K lines of Clojure: 1,414 for implementation and 584 for tests. As a very\nrough point of comparison, Basho's [official Riak 2 Java client][rjc] has\nabout 28K lines of code: 17K for code, 11K for tests. It is more complete, of\ncourse, so this isn't an apples-to-apples comparison. Still, I spent\nconsiderable effort reducing duplication in Kria, and I believe this makes\nKria code easier to read and reason about. I hope this translates to better\nreliability, too. If and when my team and/or the community wants additional\nfeatures, I'm confident they can be added with dozens or hundreds of LOC, not\nthousands.\n\n[rjc]: https://github.com/basho/riak-java-client\n\n## Usage\n\nAdd this to your `project.clj`:\n\n    [kria \"0.1.15\"]\n\nFor the following examples, I recommend using these namespace aliases:\n\n    [kria.client :as client]\n    [kria.server :as server]\n\nTo create a connection:\n\n    (defn conn-cb [asc e a] (println (if e e \"connected\")))\n    (def conn (client/connect \"127.0.0.1\" 8087 conn-cb))\n\nThe first line sets up the callback that runs after `connect` succeeds or\nfails. On failure, it returns the exception `e`. On success, it prints\n\"connected\".\n\nThe second line connects to Riak with the specified host, port, and callback.\n\nTry a ping with:\n\n    (defn ping-cb [asc e a] (println (if e e \"pong\")))\n    (server/ping conn ping-cb)\n\nGet server info with:\n\n    (defn info-cb [asc e a] (prn (or e a)))\n    (server/info conn info-cb)\n\nAll of the above calls are asynchronous. The callback functions are for\ndemonstration purposes only. In practice, write your callback functions for\nyour application's needs.\n\nYou can find more examples on how to use the API in `doc/examples`.\n\n## Connect Details\n\nThe callback for `connect` takes these arguments:\n\n  * `asc` : [`AsynchronousSocketChannel`][ASC], a Java 7 NIO.2 class that Kria\n    uses for asynchronous IO. Each Kria connection wraps exactly one\n    `AsynchronousSocketChannel`. The Javadoc is fairly readable, but if you\n    don't want to read it, perhaps the most important thing to know is that\n    each `AsynchronousSocketChannel` can only support one read or one write at\n    a time. So, if you need to make concurrent calls, you'll need more than\n    one of them.\n  * `e` : exception or `nil` if no exception.\n  * `a` : attachment, a term used in the NIO.2 documentation. Generally\n    speaking, the attachment is just a placeholder for an object to get passed\n    along if a callback succeeds. In Kria, the attachment varies based on the\n    API call. In the case of `connect`, it will be `true` on success or `nil`\n    on failure.\n\nIf you want to pool connections, use the 4 argument version of `connect` that\ntakes these inputs: `[host port ^AsynchronousChannelGroup group cb]`. To learn\nhow, read about the [AsynchronousChannelGroup][ACG] class.\n\n[ASC]: http://docs.oracle.com/javase/7/docs/api/java/nio/channels/AsynchronousSocketChannel.html\n[ACG]: http://docs.oracle.com/javase/7/docs/api/java/nio/channels/AsynchronousChannelGroup.html\n\n## Using in Applications\n\nEven though Kria is asynchronous with callbacks, it is easy to wrap it as you\nlike. You might try callback functions, Clojure atoms, and promises and see\nwhat works best.\n\nWe have found that [core.async] works great as a layer on top. Just create a\ncore.async channel in advance and have the callback put the desired return\nvalue in the core.async channel.\n\nWhen [we] write applications, we tend to create a namespace that wraps all\ncalls to Kria in a domain-specific way. That namespace provides an API that the\nrest of your application relies on. Kria is a thin wrapper over the Riak API,\nso it does not handle siblings for you; that is something your domain-specific\nlogic must decide.\n\n[core.async]: https://github.com/clojure/core.async\n[we]: http://bluemontlabs.com\n\n## History\n\nWhen I started, my goals were to:\n\n* write a simple asynchronous Clojure client\n* stay relatively close the Riak API\n* use NIO.2, available in Java 7 and later, instead of Netty\n\nMany projects use Netty, but as I learned more about it, I found that NIO.2\nprovided all I wanted without the complexity of another dependency. The\ntradeoff is that Kria requires Java 7 or later.\n\n[Netty]: http://netty.io/\n[NIO.2]: http://en.wikipedia.org/wiki/NIO.2#JDK_7_and_NIO.2\n\nOther drivers I saw written in Clojure or Java added complexity that I didn't\nneed. The goal was to have a simple layer to abstract away the low-level\nprotocol buffer interface. Other drivers seem to have different objectives.\n\nI started this project before the Java client for Riak 2 was ready. Sean from\nBasho [mentioned on the Riak mailing list][ml-1] that \"the new official Java\nclient is designed so that it would be easier to write wrapper libraries in\nother JVM languages, and to give the user the option of async or sync at the\nAPI level.\" I'd be interested to see what people think of the newer client.\n\n[ml-1]: http://lists.basho.com/pipermail/riak-users_lists.basho.com/2014-July/015578.html\n\nI used the [lein-protobuf] plugin at first, but stopped using it for these\nreasons:\n\n  1. The protobuf files change rarely, so the plugin seemed less necessary.\n  2. The plugin added complexity that did not seem necessary.\n  3. I wanted to understand the `protoc` command, including how the Java\n     classes were getting created and where they were being stored.\n  4. The plugin seemed to slow the REPL start-up time.\n\n[lein-protobuf]: https://github.com/flatland/lein-protobuf\n[riak_pb]: https://github.com/basho/riak_pb\n\nAs of September 2014, thanks to a [recommendation from Basho][ml-1], Kria uses\nthe Riak protobuf files via Maven, instead of keeping its own copy (which was\nprone to get stale).\n\n## Before Running the Tests\n\nThis section is intended for developers who want to run the included tests\nwith `lein test`.\n\n1. Since the tests use Riak Search, please ensure that search\n   is enabled. Check that your `riak.conf` file has `search = on`. If you\n   would like to test secondary indexes (2i), ensure that `storage_backend`\n   is set to `leveldb` or `memory`, ex. `storage_backend = leveldb`. Run tests\n   with `KRIA_TEST_2I=true` to test 2i.\n\n2. Also, run `test/riak-setup.sh` as root *once*, to create and activate the\n   necessary bucket types.\n\n## Message Terminology\n\nThis section is intended for developers who want to dig into the internals of\nKria. (It may also be helpful in understanding how the Riak protocol buffer\ninterface works.)\n\nHere, I go into some detail about the message components because Basho's\n[terminology of a Riak Protocol Buffer message][Riak-PB] is somewhat unclear.\nThat documentation uses the term 'message' for both the protobuf part and the\nentire data structure. This is confusing, especially when you need to be clear\nabout the lengths. That's why I use a separate name, 'payload', for the\nprotobuf component.\n\nSo, let me introduce some definitions. The entire data structure is called the\n*message*. A message consists of three pieces:\n\n  * *body length* : Bytes 0 to 3. Encodes the length of the body (e.g. the\n    rest of the message).\n  * *message code* : Byte 4. See `kria.core/message-codes`.\n  * *payload* : Optional; Bytes 5+. Encoded using Protocol Buffers.\n\nThese three pieces can be aggregated in various ways:\n\n  1. body length + message code = header\n  2. message code + payload = body\n  3. header + payload = message\n  4. body length + body = message\n  5. body length + message code + payload = message\n\nHopefully my terminology is clear. If the above five points make sense to you,\nthen you are in good shape. I have nothing new to say, but I do want to make\nsure that some things are clear.\n\nThe body length is simply the length of the body. This sounds simple, but if\nyou read the Riak documentation, you may get confused. It is *not* the length\nof the entire message; it does not include itself in the calculation. Put\nanother way:\n\n  * If there is a payload, the body length will be the length of the payload\n    plus 1.\n  * If there is no payload, the length is 1.\n\nIn both cases, the 1 comes from the message code, which is one byte long.\nAnother related term is the *payload length*, which is (hopefully clear by now)\none less than the body length.\n\n[Riak-PB]: http://docs.basho.com/riak/latest/dev/references/protocol-buffers/\n\n## Running Tests in the REPL\n\nIt may not be widely known that it is easy to run tests in the REPL.\n\nFor example:\n\n```clj\n(refresh) (run-tests 'kria.search-test)\n```\n\n## License\n\nCopyright 2014 Bluemont Labs LLC\n\nDistributed under the Eclipse Public License, the same as Clojure.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyetanalytics%2Fkria","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fyetanalytics%2Fkria","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyetanalytics%2Fkria/lists"}