{"id":50,"date":"2011-01-13T17:07:45","date_gmt":"2011-01-13T17:07:45","guid":{"rendered":"http:\/\/joose.it\/blog\/?p=50"},"modified":"2011-04-08T14:01:40","modified_gmt":"2011-04-08T14:01:40","slug":"introducing-kiokujs","status":"publish","type":"post","link":"http:\/\/joose.it\/blog\/2011\/01\/13\/introducing-kiokujs\/","title":{"rendered":"Introducing KiokuJS"},"content":{"rendered":"<h1>What<\/h1>\n<p>KiokuJS is a persistence layer for Joose. Its a freestyle port of <a href=\"http:\/\/www.iinteractive.com\/kiokudb\/\" target=\"_blank\">KiokuDB<\/a> which does the same thing in the Moose world.<\/p>\n<p>KiokuJS provides transparent storing\/retrieving for instances of  Joose classes. Native data structures (Object\/Array\/etc) can be stored  as well. \u201cTransparent\u201d means that class can be stored without any  modifications to its declaration (see also <a href=\"#but\">But<\/a>).<\/p>\n<p>KiokuJS is <strong>cross-platform<\/strong> \u2013 it runs equally well in browsers and NodeJS. KiokuJS is <strong>non-blocking<\/strong> \u2013 all interactions with DB are asynchronous.<\/p>\n<h1>Why<\/h1>\n<p>Remember the last Web2.0 project you worked on. Quite probably it was looking as:<\/p>\n<p style=\"text-align: left;\"><a href=\"..\/wp-content\/uploads\/2010\/10\/app-model.png\" target=\"_blank\"><\/a><a href=\"http:\/\/joose.it\/blog\/wp-content\/uploads\/2011\/01\/app-model.png\"><img loading=\"lazy\" class=\"aligncenter size-full wp-image-51\" style=\"border: 0pt none;\" title=\"app-model\" src=\"http:\/\/joose.it\/blog\/wp-content\/uploads\/2011\/01\/app-model.png\" alt=\"\" width=\"666\" height=\"456\" \/><\/a>Note,  that you need to define the serialization procedure 4(!) times. Even if  you use some kind of client-side helpers of modern frameworks, you  still need to (manually) map your client-side JavaScript data structures  to the storage layer.<\/p>\n<p>Meanwhile, nowadays its obvious, that JavaScript has evolved from  client-side  animation libraries into full-stack platform. There are no  reasons why  your applications can\u2019t be fully written in JavaScript and <strong>benefit from the homogeneous environment both on client and server<\/strong>.<\/p>\n<p>So the goals of KiokuJS are:<\/p>\n<ul>\n<li>eliminate all the serialization boilerplate from the application<\/li>\n<li>use a single model definition both on client and server<\/li>\n<li>encapsulate all the storage-layer details in high-level interface<\/li>\n<\/ul>\n<h1>Example<\/h1>\n<div>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\/\/ class declaration\r\n\r\nClass('Person', {\r\n\r\n    has : {\r\n        self    : null,\r\n\r\n        name    : null,\r\n\r\n        spouse  : null\r\n    },\r\n\r\n    methods : {\r\n\r\n        initialize : function () {\r\n            this.self = this \/\/ circular ref\r\n        }\r\n    }\r\n})\r\n\r\n\/\/ arbitrary data structure\r\n\r\nvar Homer = new Person({\r\n    name    : &quot;Homer&quot;\r\n})\r\n\r\nvar Marge = new Person({\r\n    name    : &quot;Marge&quot;\r\n})\r\n\r\nHomer.spouse = Marge\r\nMarge.spouse = Homer\r\n\r\n\/\/ handler setup\r\n\r\nvar handle = new KiokuJS.Backend.CouchDB({\r\n    dbURL   : 'http:\/\/local:5984\/someDB'\r\n})\r\n\r\n\/\/ storing\r\n\r\nvar scope = handle.newScope()\r\n\r\nscope.store(Homer, Marge).andThen(function (homerID, margeID) {\r\n    ...\r\n})\r\n\r\n\/\/ retrieving\r\n\r\nvar scope = handle.newScope()\r\n\r\nscope.lookUp(homerID, margeID).andThen(function (Homer2, Marge2) {\r\n\r\n    \/\/ Homer2.self   === Homer2\r\n    \/\/ Homer2.spouse  === Marge2\r\n\r\n    \/\/ Marge2.self   === Marge2\r\n    \/\/ Marge2.spouse  === Homer2\r\n})\r\n\r\n<\/pre>\n<\/div>\n<h1>How<\/h1>\n<p style=\"text-align: left;\">From the KiokuJS viewpoint, the data structures represents a cyclic, directed graph:<a href=\"..\/wp-content\/uploads\/2010\/10\/graph.png\" target=\"_blank\"><\/a><a href=\"http:\/\/joose.it\/blog\/wp-content\/uploads\/2011\/01\/graph.png\"><img loading=\"lazy\" class=\"aligncenter size-full wp-image-57\" style=\"border: 0pt none;\" title=\"graph\" src=\"http:\/\/joose.it\/blog\/wp-content\/uploads\/2011\/01\/graph.png\" alt=\"\" width=\"403\" height=\"215\" \/><\/a>Data graph is then serialized into JSON structures like:<\/p>\n<div>\n<div>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">{\r\n    &quot;className&quot;: &quot;Person&quot;,\r\n    &quot;ID&quot;: &quot;2D9E24EE-89BA-A361-B0E6-2D8A6C1226F6&quot;,\r\n    &quot;isRoot&quot;: true,\r\n    &quot;data&quot;: {\r\n        &quot;self&quot;: {\r\n            &quot;$ref&quot;: &quot;2D9E24EE-89BA-A361-B0E6-2D8A6C1226F6&quot;\r\n        },\r\n        &quot;name&quot;: &quot;Homer&quot;,\r\n        &quot;spouse&quot;: {\r\n            &quot;$ref&quot;: &quot;0CFB5A77-8B58-BC7F-9B7D-DBDD78A29AC2&quot;\r\n        }\r\n    },\r\n    &quot;$entry&quot;: true\r\n}\r\n\r\n{\r\n    &quot;className&quot;: &quot;Person&quot;,\r\n    &quot;ID&quot;: &quot;0CFB5A77-8B58-BC7F-9B7D-DBDD78A29AC2&quot;,\r\n    &quot;isRoot&quot;: true,\r\n    &quot;data&quot;: {\r\n        &quot;self&quot;: {\r\n            &quot;$ref&quot;: &quot;0CFB5A77-8B58-BC7F-9B7D-DBDD78A29AC2&quot;\r\n        },\r\n        &quot;name&quot;: &quot;Marge&quot;,\r\n        &quot;spouse&quot;: {\r\n            &quot;$ref&quot;: &quot;2D9E24EE-89BA-A361-B0E6-2D8A6C1226F6&quot;\r\n        }\r\n    },\r\n    &quot;$entry&quot;: true\r\n}<\/pre>\n<\/div>\n<\/div>\n<p>There are a number of options, defining the serialization details  (implemented as attribute traits). When required, its also possible to  provide a custom serialization format for specific class.<\/p>\n<p>Its worth to note, that all asynchronous interfaces in Kioku are implemented using the <a href=\"..\/2010\/08\/02\/asynchronous-aka-non-blocking-control-flow\/\" target=\"_blank\">continuation-passing style extension for Joose<\/a>, which provides a precise control over the asynchronous methods. The previous storing example can be elaborated like this:<\/p>\n<div>\n<div>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\/\/ storing\r\n\r\nUI.maskScreen(&quot;Please wait&quot;)\r\n\r\nscope.store(Homer, Marge).then(function (homerID, margeID) {\r\n\r\n    alert('Objects stored successfully')\r\n\r\n    this.CONTINUE()\r\n\r\n}).CATCH(function (e) {\r\n\r\n    alert('There were an exception [' + e + '] during storing operation')\r\n\r\n    this.CONTINUE()\r\n\r\n}).FINALLY(function () {\r\n\r\n    UI.unMaskScreen()\r\n\r\n}).now()<\/pre>\n<\/div>\n<\/div>\n<h1 id=\"but\">But<\/h1>\n<p>Persistence is mostly transparent, but there are some limitations.  Generally any closures-related magic won\u2019t be recognized, simply because  there are no according introspection capabilities in the language. For  example, if you have a function, tied to a scope with some closures, as  the value of the attribute:<\/p>\n<div>\n<div>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">var closure = { foo : 'bar' }\r\n\r\nhomer.magic = function () { return closure.foo }<\/pre>\n<\/div>\n<\/div>\n<p>then KiokuJS will store the function declaration only, not the scope  it was defined in. So after retrieving the instance from the backend and  running \u201chomer.magic()\u201d there will be an exception like [&#8220;closure&#8221; is  not defined].<\/p>\n<p>Another limitation is related to searching. Searching is constrained to backends capabilities only.<\/p>\n<h1>Backends<\/h1>\n<p>Kioku is backend-agnostic, but currently mostly target NoSQL  (key\/value) backends because of their simplicity, native JSON support  and HTTP APIs, which allows to directly access the DB from the  browsers.\u00a0 With some additional efforts can be implemented a relational  backend, either static (when classes definitions will be generated from  the relational schema) or dynamic (when the relational schema will be  adjusted to the classes definition).<\/p>\n<p>For the development and testing there is a \u201cHash\u201d backend. For the production \u2013 CouchDB backend.<\/p>\n<p>Test suite of Kioku is organized that way, that makes it possible to run for each backend.<\/p>\n<p>There is also a special backend (actually a role for backend) \u2013  KiokuJS.Backend.Batch, intended for usage in browsers. It allows to  combine the individual requests for separate documents into batches,  saving a lot of HTTP requests.<\/p>\n<p>Writing new backends is easy \u2013 they only need to define 4 methods.<\/p>\n<h1>Status<\/h1>\n<p>KiokuJS is at 0.01 version. This means its \u201cstable enough\u201d, has the  extensive test suite, but is mostly intended for early adopters, which  are welcome to Joose <a href=\"http:\/\/webchat.freenode.net\/?randomnick=1&amp;channels=joose&amp;prompt=1\" target=\"_blank\">IRC channel<\/a> with any questions. Currently there is no documentation.<\/p>\n<p>To install Kioku, run<\/p>\n<p>&gt; npm install kiokujs<\/p>\n<p>You may also want to install CouchDB backend with:<\/p>\n<p>&gt; npm install kiokujs-backend-couchdb<\/p>\n<p>After that this mini <a href=\"http:\/\/gist.github.com\/620582\" target=\"_blank\">demo app<\/a> should just work from NodeJS, supposing you have correct value for NODE_PATH environment variable (see items 3.x in <a href=\"http:\/\/joose.github.com\/Joose\/doc\/html\/Joose\/Manual\/Installation.html\">Joose installation<\/a>).<\/p>\n<h1>Roadmap<\/h1>\n<ul>\n<li>Add more backends \u2013 Riak and MongoDB are 1st candidacies.<\/li>\n<li>Try to implement backends for graph databases (very promising).<\/li>\n<li>Syncler (draft name) \u2013 real-time backend, which use the optimistic  replication to synchronize the state of replicas between clients.<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>What KiokuJS is a persistence layer for Joose. Its a freestyle port of KiokuDB which does the same thing in the Moose world. KiokuJS provides transparent storing\/retrieving for instances of Joose classes. Native data structures (Object\/Array\/etc) can be stored as well. \u201cTransparent\u201d means that class can be stored without any modifications to its declaration (see [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0},"categories":[4],"tags":[9],"_links":{"self":[{"href":"http:\/\/joose.it\/blog\/wp-json\/wp\/v2\/posts\/50"}],"collection":[{"href":"http:\/\/joose.it\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/joose.it\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/joose.it\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/joose.it\/blog\/wp-json\/wp\/v2\/comments?post=50"}],"version-history":[{"count":9,"href":"http:\/\/joose.it\/blog\/wp-json\/wp\/v2\/posts\/50\/revisions"}],"predecessor-version":[{"id":274,"href":"http:\/\/joose.it\/blog\/wp-json\/wp\/v2\/posts\/50\/revisions\/274"}],"wp:attachment":[{"href":"http:\/\/joose.it\/blog\/wp-json\/wp\/v2\/media?parent=50"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/joose.it\/blog\/wp-json\/wp\/v2\/categories?post=50"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/joose.it\/blog\/wp-json\/wp\/v2\/tags?post=50"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}