diff --git a/404.html b/404.html index 19ecd031..4e3bf962 100644 --- a/404.html +++ b/404.html @@ -10,13 +10,13 @@ Page Not Found | Stencil - +
Skip to main content

Page Not Found

We could not find what you were looking for.

Please contact the owner of the site that linked you to the original URL and let them know their link is broken.

- + \ No newline at end of file diff --git a/assets/js/3b8c55ea.2891c04d.js b/assets/js/3b8c55ea.f0595028.js similarity index 99% rename from assets/js/3b8c55ea.2891c04d.js rename to assets/js/3b8c55ea.f0595028.js index 63dedc66..9a5844a3 100644 --- a/assets/js/3b8c55ea.2891c04d.js +++ b/assets/js/3b8c55ea.f0595028.js @@ -1 +1 @@ -"use strict";(self.webpackChunkstencil=self.webpackChunkstencil||[]).push([[217],{3905:function(e,t,n){n.d(t,{Zo:function(){return p},kt:function(){return m}});var a=n(7294);function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function l(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function i(e){for(var t=1;t=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var s=a.createContext({}),c=function(e){var t=a.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},p=function(e){var t=c(e.components);return a.createElement(s.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},d=a.forwardRef((function(e,t){var n=e.components,r=e.mdxType,l=e.originalType,s=e.parentName,p=o(e,["components","mdxType","originalType","parentName"]),d=c(n),m=r,k=d["".concat(s,".").concat(m)]||d[m]||u[m]||l;return n?a.createElement(k,i(i({ref:t},p),{},{components:n})):a.createElement(k,i({ref:t},p))}));function m(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var l=n.length,i=new Array(l);i[0]=d;var o={};for(var s in t)hasOwnProperty.call(t,s)&&(o[s]=t[s]);o.originalType=e,o.mdxType="string"==typeof e?e:r,i[1]=o;for(var c=2;c=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var s=a.createContext({}),c=function(e){var t=a.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},p=function(e){var t=c(e.components);return a.createElement(s.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},d=a.forwardRef((function(e,t){var n=e.components,r=e.mdxType,l=e.originalType,s=e.parentName,p=o(e,["components","mdxType","originalType","parentName"]),d=c(n),m=r,k=d["".concat(s,".").concat(m)]||d[m]||u[m]||l;return n?a.createElement(k,i(i({ref:t},p),{},{components:n})):a.createElement(k,i({ref:t},p))}));function m(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var l=n.length,i=new Array(l);i[0]=d;var o={};for(var s in t)hasOwnProperty.call(t,s)&&(o[s]=t[s]);o.originalType=e,o.mdxType="string"==typeof e?e:r,i[1]=o;for(var c=2;c=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var o=a.createContext({}),c=function(e){var t=a.useContext(o),n=t;return e&&(n="function"==typeof e?e(t):l(l({},t),e)),n},p=function(e){var t=c(e.components);return a.createElement(o.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},d=a.forwardRef((function(e,t){var n=e.components,r=e.mdxType,i=e.originalType,o=e.parentName,p=s(e,["components","mdxType","originalType","parentName"]),d=c(n),g=r,m=d["".concat(o,".").concat(g)]||d[g]||u[g]||i;return n?a.createElement(m,l(l({ref:t},p),{},{components:n})):a.createElement(m,l({ref:t},p))}));function g(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var i=n.length,l=new Array(i);l[0]=d;var s={};for(var o in t)hasOwnProperty.call(t,o)&&(s[o]=t[o]);s.originalType=e,s.mdxType="string"==typeof e?e:r,l[1]=s;for(var c=2;c\n org.raystack\n stencil\n 0.5.0\n\n")),(0,i.kt)("h3",{id:"creating-a-stencil-client-instance"},"Creating a stencil Client instance"),(0,i.kt)("p",null,"Stencil client can be created in different modes."),(0,i.kt)("h4",{id:"loading-descriptor-from-protobuf-class-available-in-the-classpath"},"Loading Descriptor from Protobuf Class available in the classpath"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-java"},"import org.raystack.stencil.client.StencilClient;\nimport org.raystack.stencil.StencilClientFactory;\n\nStencilClient stencilClient = StencilClientFactory.getClient();\n")),(0,i.kt)("h4",{id:"create-client-with-remote-url"},"Create client with remote URL"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-java"},'import org.raystack.stencil.config.StencilConfig;\n\nString url = "http://url/to/proto/descriptor-set/file";\nStencilClient stencilClient = StencilClientFacorty.getClient(url, StencilConfig.builder().build());\n')),(0,i.kt)("h4",{id:"creating-multiurl-client"},"Creating MultiURL client"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-java"},'import org.raystack.stencil.config.StencilConfig;\n\nArrayList urls = new ArrayList();\nurls.add("http://localhost:8082/v1beta1/...");\nStencilClient stencilClient = StencilClientFacorty.getClient(urls, StencilConfig.builder().build());\n')),(0,i.kt)("h4",{id:"with-statsd-client-for-monitoring"},"With StatsD client for monitoring"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-java"},'// From https://github.com/tim-group/java-statsd-client\nimport com.timgroup.statsd.StatsDClient;\nimport com.timgroup.statsd.NonBlockingStatsDClient;\n\nStatsDClient statDClient = new NonBlockingStatsDClient("my.prefix", "statsd-host", 8125);\nStencilClient stencilClient = StencilClientFactory.getClient(url, StencilConfig.builder().statsDClient(statsDClient).build());\n')),(0,i.kt)("h4",{id:"with-schema-update-listener"},"With Schema Update Listener"),(0,i.kt)("p",null,"Whenever schema has changed this listener will be called."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-java"},"import org.raystack.stencil.SchemaUpdateListener;\n\nSchemaUpdateListener updateListener = new SchemaUpdateListenerImpl();\nStencilClient stencilClient = StencilClientFactory.getClient(url, StencilConfig.builder().updateListener(updateListener).build());\n")),(0,i.kt)("h4",{id:"with-version-based-refresh-strategy"},"With version based refresh strategy"),(0,i.kt)("p",null,"If url belongs to stencil server, client can choose to refresh schema data only if there is a new version available."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-java"},"import org.raystack.stencil.cache.SchemaRefreshStrategy;\n\nStencilConfig config = StencilConfig.builder().refreshStrategy(SchemaRefreshStrategy.versionBasedRefresh()).build();\nStencilClient stencilClient = StencilClientFactory.getClient(url, config);\n")),(0,i.kt)("h4",{id:"passing-custom-headers"},"Passing custom headers"),(0,i.kt)("p",null,"While sending request to specified URL, client can be configured to pass headers as well."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-java"},'import org.apache.http.Header;\nimport org.apache.http.HttpHeaders;\nimport org.apache.http.message.BasicHeader;\n\nHeader authHeader = new BasicHeader(HttpHeaders.AUTHORIZATION, "Bearer " + token);\nList
headers = new ArrayList
();\nheaders.add(authHeader);\nStencilConfig config = StencilConfig.builder().fetchHeaders(headers).build();\nStencilClient stencilClient = StencilClientFactory.getClient(url, config);\n')),(0,i.kt)("h3",{id:"getting-descriptor"},"Getting descriptor"),(0,i.kt)("p",null,"Given the name of the Proto-Class StencilClient returns the Descriptor for it."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-java"},"import com.google.protobuf.Descriptors;\nimport com.google.protobuf.DynamicMessage;\n\nDescriptors.Descriptor descriptor = stencilClient.get(protoClassName);\n")),(0,i.kt)("h3",{id:"parsing-message"},"Parsing message"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-java"},"import com.google.protobuf.Descriptors;\nimport com.google.protobuf.DynamicMessage;\n\nDescriptors.Descriptor descriptor = stencilClient.get(protoClassName);\nDynamicMessage message = DynamicMessage.parseFrom(descriptor, bytes);\n")),(0,i.kt)("h4",{id:"using-parser-interface"},"Using Parser interface"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-java"},'import org.raystack.stencil.Parser;\nimport com.google.protobuf.DynamicMessage;\n\nParser protoParser = stencilClient.getParser("com.example.proto.schema");\nDynamicMessage message = protoParser.parse(bytes)\n')),(0,i.kt)("h3",{id:"publishing"},"Publishing"),(0,i.kt)("p",null,"The client is published and released via github workflow and uses github tag for versioning."),(0,i.kt)("h3",{id:"notes"},"Notes"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"Stencil uses ",(0,i.kt)("inlineCode",{parentName:"li"},"java-statsd-client")," from ",(0,i.kt)("inlineCode",{parentName:"li"},"com.timgroup"),", Please use the same client in your application for statsd")))}g.isMDXComponent=!0}}]); \ No newline at end of file +"use strict";(self.webpackChunkstencil=self.webpackChunkstencil||[]).push([[58],{3905:function(e,t,n){n.d(t,{Zo:function(){return p},kt:function(){return g}});var a=n(7294);function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function l(e){for(var t=1;t=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var o=a.createContext({}),c=function(e){var t=a.useContext(o),n=t;return e&&(n="function"==typeof e?e(t):l(l({},t),e)),n},p=function(e){var t=c(e.components);return a.createElement(o.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},d=a.forwardRef((function(e,t){var n=e.components,r=e.mdxType,i=e.originalType,o=e.parentName,p=s(e,["components","mdxType","originalType","parentName"]),d=c(n),g=r,m=d["".concat(o,".").concat(g)]||d[g]||u[g]||i;return n?a.createElement(m,l(l({ref:t},p),{},{components:n})):a.createElement(m,l({ref:t},p))}));function g(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var i=n.length,l=new Array(i);l[0]=d;var s={};for(var o in t)hasOwnProperty.call(t,o)&&(s[o]=t[o]);s.originalType=e,s.mdxType="string"==typeof e?e:r,l[1]=s;for(var c=2;c\n org.raystack\n stencil\n 0.5.1\n\n")),(0,i.kt)("h3",{id:"creating-a-stencil-client-instance"},"Creating a stencil Client instance"),(0,i.kt)("p",null,"Stencil client can be created in different modes."),(0,i.kt)("h4",{id:"loading-descriptor-from-protobuf-class-available-in-the-classpath"},"Loading Descriptor from Protobuf Class available in the classpath"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-java"},"import org.raystack.stencil.client.StencilClient;\nimport org.raystack.stencil.StencilClientFactory;\n\nStencilClient stencilClient = StencilClientFactory.getClient();\n")),(0,i.kt)("h4",{id:"create-client-with-remote-url"},"Create client with remote URL"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-java"},'import org.raystack.stencil.config.StencilConfig;\n\nString url = "http://url/to/proto/descriptor-set/file";\nStencilClient stencilClient = StencilClientFacorty.getClient(url, StencilConfig.builder().build());\n')),(0,i.kt)("h4",{id:"creating-multiurl-client"},"Creating MultiURL client"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-java"},'import org.raystack.stencil.config.StencilConfig;\n\nArrayList urls = new ArrayList();\nurls.add("http://localhost:8082/v1beta1/...");\nStencilClient stencilClient = StencilClientFacorty.getClient(urls, StencilConfig.builder().build());\n')),(0,i.kt)("h4",{id:"with-statsd-client-for-monitoring"},"With StatsD client for monitoring"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-java"},'// From https://github.com/tim-group/java-statsd-client\nimport com.timgroup.statsd.StatsDClient;\nimport com.timgroup.statsd.NonBlockingStatsDClient;\n\nStatsDClient statDClient = new NonBlockingStatsDClient("my.prefix", "statsd-host", 8125);\nStencilClient stencilClient = StencilClientFactory.getClient(url, StencilConfig.builder().statsDClient(statsDClient).build());\n')),(0,i.kt)("h4",{id:"with-schema-update-listener"},"With Schema Update Listener"),(0,i.kt)("p",null,"Whenever schema has changed this listener will be called."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-java"},"import org.raystack.stencil.SchemaUpdateListener;\n\nSchemaUpdateListener updateListener = new SchemaUpdateListenerImpl();\nStencilClient stencilClient = StencilClientFactory.getClient(url, StencilConfig.builder().updateListener(updateListener).build());\n")),(0,i.kt)("h4",{id:"with-version-based-refresh-strategy"},"With version based refresh strategy"),(0,i.kt)("p",null,"If url belongs to stencil server, client can choose to refresh schema data only if there is a new version available."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-java"},"import org.raystack.stencil.cache.SchemaRefreshStrategy;\n\nStencilConfig config = StencilConfig.builder().refreshStrategy(SchemaRefreshStrategy.versionBasedRefresh()).build();\nStencilClient stencilClient = StencilClientFactory.getClient(url, config);\n")),(0,i.kt)("h4",{id:"passing-custom-headers"},"Passing custom headers"),(0,i.kt)("p",null,"While sending request to specified URL, client can be configured to pass headers as well."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-java"},'import org.apache.http.Header;\nimport org.apache.http.HttpHeaders;\nimport org.apache.http.message.BasicHeader;\n\nHeader authHeader = new BasicHeader(HttpHeaders.AUTHORIZATION, "Bearer " + token);\nList
headers = new ArrayList
();\nheaders.add(authHeader);\nStencilConfig config = StencilConfig.builder().fetchHeaders(headers).build();\nStencilClient stencilClient = StencilClientFactory.getClient(url, config);\n')),(0,i.kt)("h3",{id:"getting-descriptor"},"Getting descriptor"),(0,i.kt)("p",null,"Given the name of the Proto-Class StencilClient returns the Descriptor for it."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-java"},"import com.google.protobuf.Descriptors;\nimport com.google.protobuf.DynamicMessage;\n\nDescriptors.Descriptor descriptor = stencilClient.get(protoClassName);\n")),(0,i.kt)("h3",{id:"parsing-message"},"Parsing message"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-java"},"import com.google.protobuf.Descriptors;\nimport com.google.protobuf.DynamicMessage;\n\nDescriptors.Descriptor descriptor = stencilClient.get(protoClassName);\nDynamicMessage message = DynamicMessage.parseFrom(descriptor, bytes);\n")),(0,i.kt)("h4",{id:"using-parser-interface"},"Using Parser interface"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-java"},'import org.raystack.stencil.Parser;\nimport com.google.protobuf.DynamicMessage;\n\nParser protoParser = stencilClient.getParser("com.example.proto.schema");\nDynamicMessage message = protoParser.parse(bytes)\n')),(0,i.kt)("h3",{id:"publishing"},"Publishing"),(0,i.kt)("p",null,"The client is published and released via github workflow and uses github tag for versioning."),(0,i.kt)("h3",{id:"notes"},"Notes"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"Stencil uses ",(0,i.kt)("inlineCode",{parentName:"li"},"java-statsd-client")," from ",(0,i.kt)("inlineCode",{parentName:"li"},"com.timgroup"),", Please use the same client in your application for statsd")))}g.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/690cf7c6.b08a952e.js b/assets/js/690cf7c6.8e8fce2d.js similarity index 99% rename from assets/js/690cf7c6.b08a952e.js rename to assets/js/690cf7c6.8e8fce2d.js index fd9edc88..7aca021e 100644 --- a/assets/js/690cf7c6.b08a952e.js +++ b/assets/js/690cf7c6.8e8fce2d.js @@ -1 +1 @@ -"use strict";(self.webpackChunkstencil=self.webpackChunkstencil||[]).push([[614],{3905:function(e,t,a){a.d(t,{Zo:function(){return s},kt:function(){return c}});var n=a(7294);function r(e,t,a){return t in e?Object.defineProperty(e,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[t]=a,e}function l(e,t){var a=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),a.push.apply(a,n)}return a}function i(e){for(var t=1;t=0||(r[a]=e[a]);return r}(e,t);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(r[a]=e[a])}return r}var p=n.createContext({}),m=function(e){var t=n.useContext(p),a=t;return e&&(a="function"==typeof e?e(t):i(i({},t),e)),a},s=function(e){var t=m(e.components);return n.createElement(p.Provider,{value:t},e.children)},d={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},u=n.forwardRef((function(e,t){var a=e.components,r=e.mdxType,l=e.originalType,p=e.parentName,s=o(e,["components","mdxType","originalType","parentName"]),u=m(a),c=r,k=u["".concat(p,".").concat(c)]||u[c]||d[c]||l;return a?n.createElement(k,i(i({ref:t},s),{},{components:a})):n.createElement(k,i({ref:t},s))}));function c(e,t){var a=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var l=a.length,i=new Array(l);i[0]=u;var o={};for(var p in t)hasOwnProperty.call(t,p)&&(o[p]=t[p]);o.originalType=e,o.mdxType="string"==typeof e?e:r,i[1]=o;for(var m=2;m"\n :refresh-cache true\n :refresh-strategy :version-based-refresh\n :headers {"" "
"}))\n')),(0,l.kt)("ol",{start:2},(0,l.kt)("li",{parentName:"ol"},"To serialize data from clojure map")),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-clojure"},'(:require [stencil.core :refer [serialize]])\n\n(def serialized-data\n (serialize client "org.raystack.CljTest" {:name "Foo"\n :address {:street "bar"}\n :email-list ["a@example.com" "b@b.com"]\n :gender :NON-BINARY\n :age 10}))\n')),(0,l.kt)("ol",{start:3},(0,l.kt)("li",{parentName:"ol"},"Deserialize data from bytes to clojure map")),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-clojure"},'(:require [stencil.core :refer [deserialize]])\n\n(deserialize client "org.raystack.CljTest" serialized-data)\n;; prints\n;; {:name "Foo"\n;; :address {:street "bar"}\n;; :email-list ["a@example.com" "b@b.com"]\n;; :gender :NON-BINARY\n;; :age 10}\n')),(0,l.kt)("h2",{id:"protocol-buffers---clojure-interop"},"Protocol buffers - Clojure interop"),(0,l.kt)("table",null,(0,l.kt)("thead",{parentName:"table"},(0,l.kt)("tr",{parentName:"thead"},(0,l.kt)("th",{parentName:"tr",align:null},"Protobuf"),(0,l.kt)("th",{parentName:"tr",align:null},"Clojure"),(0,l.kt)("th",{parentName:"tr",align:null},"Notes"))),(0,l.kt)("tbody",{parentName:"table"},(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"field names"),(0,l.kt)("td",{parentName:"tr",align:null},"keywords in kebab case"),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},"name")," -> ",(0,l.kt)("inlineCode",{parentName:"td"},":name"),", ",(0,l.kt)("inlineCode",{parentName:"td"},"field_name")," -> ",(0,l.kt)("inlineCode",{parentName:"td"},":field-name"))),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"scalar fields"),(0,l.kt)("td",{parentName:"tr",align:null},"Values follow ",(0,l.kt)("a",{parentName:"td",href:"https://developers.google.com/protocol-buffers/docs/proto3#scalar"},"protobuf-java scalar value mappings")),(0,l.kt)("td",{parentName:"tr",align:null})),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"enums"),(0,l.kt)("td",{parentName:"tr",align:null},"Values converted as keywords of enum's original value"),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},"UNKNOWN")," -> ",(0,l.kt)("inlineCode",{parentName:"td"},":UNKNOWN"))),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"messages"),(0,l.kt)("td",{parentName:"tr",align:null},"clojure map"),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},"message Hello {string name = 1;}"),' -> {:name "raystack"}')),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"repeated fields"),(0,l.kt)("td",{parentName:"tr",align:null},"clojure vector"),(0,l.kt)("td",{parentName:"tr",align:null})),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"one-of fields"),(0,l.kt)("td",{parentName:"tr",align:null},"treated as regular fields"),(0,l.kt)("td",{parentName:"tr",align:null},"if two fields are set that are part of one-of, last seen value is considered while serializing data")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"map"),(0,l.kt)("td",{parentName:"tr",align:null},"map values follow it's ",(0,l.kt)("a",{parentName:"td",href:"https://developers.google.com/protocol-buffers/docs/proto3#backwards_compatibility"},"wire representation")),(0,l.kt)("td",{parentName:"tr",align:null},"for ",(0,l.kt)("inlineCode",{parentName:"td"},"map")," type, example value will be ",(0,l.kt)("inlineCode",{parentName:"td"},'[{:key "key" :value "value"}]'))))),(0,l.kt)("p",null,(0,l.kt)("strong",{parentName:"p"},"Note on errors:"),"\nSerialize will throw error in following cases"),(0,l.kt)("ol",null,(0,l.kt)("li",{parentName:"ol"},"unknown field is passed that's not present in schema ",(0,l.kt)("inlineCode",{parentName:"li"},"{:cause :unknown-field :info {:field-name }}")),(0,l.kt)("li",{parentName:"ol"},"if non-collection type is passed to repeated field ",(0,l.kt)("inlineCode",{parentName:"li"},"{:cause :not-a-collection :info {:value }}")),(0,l.kt)("li",{parentName:"ol"},"If unknown enum value passed that's not present in schema ",(0,l.kt)("inlineCode",{parentName:"li"},"{:cause :unknown-enum-value :info {:field-name }}"))),(0,l.kt)("h2",{id:"api"},"API"),(0,l.kt)("ul",null,(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("p",{parentName:"li"},(0,l.kt)("inlineCode",{parentName:"p"},"create-client (client-config)")),(0,l.kt)("p",{parentName:"li"},"Returns a new Stencil Clojure client instance by passing client-config."),(0,l.kt)("h3",{parentName:"li",id:"client-config-structure-"},"Client config structure :"),(0,l.kt)("table",{parentName:"li"},(0,l.kt)("thead",{parentName:"table"},(0,l.kt)("tr",{parentName:"thead"},(0,l.kt)("th",{parentName:"tr",align:null},"Key"),(0,l.kt)("th",{parentName:"tr",align:null},"Type"),(0,l.kt)("th",{parentName:"tr",align:null},"Description"))),(0,l.kt)("tbody",{parentName:"table"},(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},"url")),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("em",{parentName:"td"},"String")),(0,l.kt)("td",{parentName:"tr",align:null},"Stencil url to fetch latest descriptor sets")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},"refresh-cache")),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("em",{parentName:"td"},"Boolean")),(0,l.kt)("td",{parentName:"tr",align:null},"Whether the cache should be refreshed or not")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},"refresh-ttl")),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("em",{parentName:"td"},"Integer")),(0,l.kt)("td",{parentName:"tr",align:null},"Cache TTL in minutes")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},"request-timeout")),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("em",{parentName:"td"},"Integer")),(0,l.kt)("td",{parentName:"tr",align:null},"Request timeout in milliseconds")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},"request-backoff-time")),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("em",{parentName:"td"},"Integer")),(0,l.kt)("td",{parentName:"tr",align:null},"Request back off time in minutes")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},"retry-count")),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("em",{parentName:"td"},"Integer")),(0,l.kt)("td",{parentName:"tr",align:null},"Number of retries to be made to fetch descriptor sets")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},"headers")),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("em",{parentName:"td"},"Map")),(0,l.kt)("td",{parentName:"tr",align:null},"Map with key as header key and value as header value, which will be passed to stencil server")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},"refresh-strategy")),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("em",{parentName:"td"},"keyword")),(0,l.kt)("td",{parentName:"tr",align:null},"Possible values :version-based-refresh, :long-polling-refresh. Default :long-polling-refresh")))),(0,l.kt)("p",{parentName:"li"},"Example:"),(0,l.kt)("pre",{parentName:"li"},(0,l.kt)("code",{parentName:"pre",className:"language-clojure"},' (let [sample-client-config {:url "https://example-url"\n :refresh-cache true\n :refresh-ttl 100\n :request-timeout 10000\n :request-backoff-time 100\n :retry-count 3\n :headers {"Authorization" "Bearer "}\n :refresh-strategy :version-based-refresh\n }]\n (create-client sample-client-config))\n'))),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("p",{parentName:"li"},(0,l.kt)("inlineCode",{parentName:"p"},"get-descriptor (client proto-class-name)")),(0,l.kt)("p",{parentName:"li"},"Returns protobuf descriptor object for the given protobuf class name."),(0,l.kt)("h3",{parentName:"li",id:"argument-list-"},"Argument list :"),(0,l.kt)("table",{parentName:"li"},(0,l.kt)("thead",{parentName:"table"},(0,l.kt)("tr",{parentName:"thead"},(0,l.kt)("th",{parentName:"tr",align:null},"Key"),(0,l.kt)("th",{parentName:"tr",align:null},"Type"),(0,l.kt)("th",{parentName:"tr",align:null},"Description"))),(0,l.kt)("tbody",{parentName:"table"},(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},"client")),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("em",{parentName:"td"},"Object")),(0,l.kt)("td",{parentName:"tr",align:null},"Instantiated Clojure client object")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},"proto-class-name")),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("em",{parentName:"td"},"String")),(0,l.kt)("td",{parentName:"tr",align:null},"Name of the proto class whose proto descriptor object is required")))),(0,l.kt)("h3",{parentName:"li",id:"response-structure"},"Response structure"),(0,l.kt)("table",{parentName:"li"},(0,l.kt)("thead",{parentName:"table"},(0,l.kt)("tr",{parentName:"thead"},(0,l.kt)("th",{parentName:"tr",align:null},"Value"),(0,l.kt)("th",{parentName:"tr",align:null},"Type"),(0,l.kt)("th",{parentName:"tr",align:null},"Description"))),(0,l.kt)("tbody",{parentName:"table"},(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("strong",{parentName:"td"},"proto-desc")),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("em",{parentName:"td"},"Object")),(0,l.kt)("td",{parentName:"tr",align:null},"Protobuf descriptor for given proto class name")))),(0,l.kt)("p",{parentName:"li"},"Example:"),(0,l.kt)("pre",{parentName:"li"},(0,l.kt)("code",{parentName:"pre",className:"language-clojure"},'(let [client (create-client sample-client-config)\n proto-package "org.raystack.stencil_clj_test"\n proto-class-name "Scalar"\n fully-qualified-proto-name (str proto-package "." proto-class-name)]\n (get-descriptor client fully-qualified-proto-name))\n'))),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("p",{parentName:"li"},(0,l.kt)("inlineCode",{parentName:"p"},"deserialize (client proto-class-name data)")),(0,l.kt)("p",{parentName:"li"},"Returns Clojure map for the given protobuf encoded byte array and protobuf class name."),(0,l.kt)("h3",{parentName:"li",id:"argument-list--1"},"Argument list :"),(0,l.kt)("table",{parentName:"li"},(0,l.kt)("thead",{parentName:"table"},(0,l.kt)("tr",{parentName:"thead"},(0,l.kt)("th",{parentName:"tr",align:null},"Key"),(0,l.kt)("th",{parentName:"tr",align:null},"Type"),(0,l.kt)("th",{parentName:"tr",align:null},"Description"))),(0,l.kt)("tbody",{parentName:"table"},(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},"client")),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("em",{parentName:"td"},"Object")),(0,l.kt)("td",{parentName:"tr",align:null},"Instantiated Clojure client object")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},"proto-class-name")),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("em",{parentName:"td"},"String")),(0,l.kt)("td",{parentName:"tr",align:null},"Name of the proto class whose proto descriptor object is required")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},"data")),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("em",{parentName:"td"},"Byte-Array")),(0,l.kt)("td",{parentName:"tr",align:null},"Data (byte-array) to be deserialized using proto-descriptor object")))),(0,l.kt)("h3",{parentName:"li",id:"response-structure-1"},"Response structure"),(0,l.kt)("table",{parentName:"li"},(0,l.kt)("thead",{parentName:"table"},(0,l.kt)("tr",{parentName:"thead"},(0,l.kt)("th",{parentName:"tr",align:null},"Value"),(0,l.kt)("th",{parentName:"tr",align:null},"Type"),(0,l.kt)("th",{parentName:"tr",align:null},"Description"))),(0,l.kt)("tbody",{parentName:"table"},(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("strong",{parentName:"td"},"deserialized-message")),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("em",{parentName:"td"},"PersistentArrayMap")),(0,l.kt)("td",{parentName:"tr",align:null},"Deserialized message (Clojure Map)")))),(0,l.kt)("p",{parentName:"li"},"Example:"),(0,l.kt)("pre",{parentName:"li"},(0,l.kt)("code",{parentName:"pre",className:"language-clojure"},'(let [client (create-client sample-client-config)\n proto-package "org.raystack.stencil_clj_test"\n proto-class-name "Scalar"\n fully-qualified-proto-name (str proto-package "." proto-class-name)\n proto-desc (get-descriptor client fully-qualified-proto-name)\n data-to-deserialize (serialize client fully-qualified-proto-name{:field-one 1.25})]\n (deserialize client fully-qualified-proto-name data-to-deserialize))\n'))),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("p",{parentName:"li"},(0,l.kt)("inlineCode",{parentName:"p"},"serialize (client proto-class-name map)")),(0,l.kt)("p",{parentName:"li"},"Returns protobuf encoded byte array for the given Clojure and protobuf class name."),(0,l.kt)("h3",{parentName:"li",id:"argument-list--2"},"Argument list :"),(0,l.kt)("table",{parentName:"li"},(0,l.kt)("thead",{parentName:"table"},(0,l.kt)("tr",{parentName:"thead"},(0,l.kt)("th",{parentName:"tr",align:null},"Key"),(0,l.kt)("th",{parentName:"tr",align:null},"Type"),(0,l.kt)("th",{parentName:"tr",align:null},"Description"))),(0,l.kt)("tbody",{parentName:"table"},(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},"client")),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("em",{parentName:"td"},"Object")),(0,l.kt)("td",{parentName:"tr",align:null},"Instantiated Clojure client object")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},"proto-class-name")),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("em",{parentName:"td"},"String")),(0,l.kt)("td",{parentName:"tr",align:null},"Name of the proto class whose proto descriptor object is required")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},"map")),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("em",{parentName:"td"},"PersistentArrayMap")),(0,l.kt)("td",{parentName:"tr",align:null},"Data (in the form of map) to be serialized using proto descriptor object")))),(0,l.kt)("h3",{parentName:"li",id:"response-structure-2"},"Response structure"),(0,l.kt)("table",{parentName:"li"},(0,l.kt)("thead",{parentName:"table"},(0,l.kt)("tr",{parentName:"thead"},(0,l.kt)("th",{parentName:"tr",align:null},"Value"),(0,l.kt)("th",{parentName:"tr",align:null},"Type"),(0,l.kt)("th",{parentName:"tr",align:null},"Description"))),(0,l.kt)("tbody",{parentName:"table"},(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("strong",{parentName:"td"},"serialized-message")),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("em",{parentName:"td"},"Byte-Array")),(0,l.kt)("td",{parentName:"tr",align:null},"Serialized message (byte-array)")))),(0,l.kt)("p",{parentName:"li"},"Example:"),(0,l.kt)("pre",{parentName:"li"},(0,l.kt)("code",{parentName:"pre",className:"language-clojure"},'(let [client (create-client sample-client-config)\n proto-package "org.raystack.stencil_clj_test"\n proto-class-name "Scalar"\n fully-qualified-proto-name (str proto-package "." proto-class-name)\n proto-desc (get-descriptor client fully-qualified-proto-name)]\n (serialize client fully-qualified-proto-name {:field-one 1.25}))\n')))),(0,l.kt)("h2",{id:"development"},"Development"),(0,l.kt)("ul",null,(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("p",{parentName:"li"},"Ensure ",(0,l.kt)("a",{parentName:"p",href:"https://leiningen.org/"},"leiningen")," is installed.")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("p",{parentName:"li"},"Run tests: ",(0,l.kt)("inlineCode",{parentName:"p"},"lein clean && lein javac && lein test"))),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("p",{parentName:"li"},"Run formatting: ",(0,l.kt)("inlineCode",{parentName:"p"},"lein cljfmt fix")))))}c.isMDXComponent=!0}}]); \ No newline at end of file +"use strict";(self.webpackChunkstencil=self.webpackChunkstencil||[]).push([[614],{3905:function(e,t,a){a.d(t,{Zo:function(){return s},kt:function(){return c}});var n=a(7294);function r(e,t,a){return t in e?Object.defineProperty(e,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[t]=a,e}function l(e,t){var a=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),a.push.apply(a,n)}return a}function i(e){for(var t=1;t=0||(r[a]=e[a]);return r}(e,t);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(r[a]=e[a])}return r}var p=n.createContext({}),m=function(e){var t=n.useContext(p),a=t;return e&&(a="function"==typeof e?e(t):i(i({},t),e)),a},s=function(e){var t=m(e.components);return n.createElement(p.Provider,{value:t},e.children)},d={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},u=n.forwardRef((function(e,t){var a=e.components,r=e.mdxType,l=e.originalType,p=e.parentName,s=o(e,["components","mdxType","originalType","parentName"]),u=m(a),c=r,k=u["".concat(p,".").concat(c)]||u[c]||d[c]||l;return a?n.createElement(k,i(i({ref:t},s),{},{components:a})):n.createElement(k,i({ref:t},s))}));function c(e,t){var a=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var l=a.length,i=new Array(l);i[0]=u;var o={};for(var p in t)hasOwnProperty.call(t,p)&&(o[p]=t[p]);o.originalType=e,o.mdxType="string"==typeof e?e:r,i[1]=o;for(var m=2;m"\n :refresh-cache true\n :refresh-strategy :version-based-refresh\n :headers {"" "
"}))\n')),(0,l.kt)("ol",{start:2},(0,l.kt)("li",{parentName:"ol"},"To serialize data from clojure map")),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-clojure"},'(:require [stencil.core :refer [serialize]])\n\n(def serialized-data\n (serialize client "org.raystack.CljTest" {:name "Foo"\n :address {:street "bar"}\n :email-list ["a@example.com" "b@b.com"]\n :gender :NON-BINARY\n :age 10}))\n')),(0,l.kt)("ol",{start:3},(0,l.kt)("li",{parentName:"ol"},"Deserialize data from bytes to clojure map")),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-clojure"},'(:require [stencil.core :refer [deserialize]])\n\n(deserialize client "org.raystack.CljTest" serialized-data)\n;; prints\n;; {:name "Foo"\n;; :address {:street "bar"}\n;; :email-list ["a@example.com" "b@b.com"]\n;; :gender :NON-BINARY\n;; :age 10}\n')),(0,l.kt)("h2",{id:"protocol-buffers---clojure-interop"},"Protocol buffers - Clojure interop"),(0,l.kt)("table",null,(0,l.kt)("thead",{parentName:"table"},(0,l.kt)("tr",{parentName:"thead"},(0,l.kt)("th",{parentName:"tr",align:null},"Protobuf"),(0,l.kt)("th",{parentName:"tr",align:null},"Clojure"),(0,l.kt)("th",{parentName:"tr",align:null},"Notes"))),(0,l.kt)("tbody",{parentName:"table"},(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"field names"),(0,l.kt)("td",{parentName:"tr",align:null},"keywords in kebab case"),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},"name")," -> ",(0,l.kt)("inlineCode",{parentName:"td"},":name"),", ",(0,l.kt)("inlineCode",{parentName:"td"},"field_name")," -> ",(0,l.kt)("inlineCode",{parentName:"td"},":field-name"))),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"scalar fields"),(0,l.kt)("td",{parentName:"tr",align:null},"Values follow ",(0,l.kt)("a",{parentName:"td",href:"https://developers.google.com/protocol-buffers/docs/proto3#scalar"},"protobuf-java scalar value mappings")),(0,l.kt)("td",{parentName:"tr",align:null})),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"enums"),(0,l.kt)("td",{parentName:"tr",align:null},"Values converted as keywords of enum's original value"),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},"UNKNOWN")," -> ",(0,l.kt)("inlineCode",{parentName:"td"},":UNKNOWN"))),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"messages"),(0,l.kt)("td",{parentName:"tr",align:null},"clojure map"),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},"message Hello {string name = 1;}"),' -> {:name "raystack"}')),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"repeated fields"),(0,l.kt)("td",{parentName:"tr",align:null},"clojure vector"),(0,l.kt)("td",{parentName:"tr",align:null})),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"one-of fields"),(0,l.kt)("td",{parentName:"tr",align:null},"treated as regular fields"),(0,l.kt)("td",{parentName:"tr",align:null},"if two fields are set that are part of one-of, last seen value is considered while serializing data")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"map"),(0,l.kt)("td",{parentName:"tr",align:null},"map values follow it's ",(0,l.kt)("a",{parentName:"td",href:"https://developers.google.com/protocol-buffers/docs/proto3#backwards_compatibility"},"wire representation")),(0,l.kt)("td",{parentName:"tr",align:null},"for ",(0,l.kt)("inlineCode",{parentName:"td"},"map")," type, example value will be ",(0,l.kt)("inlineCode",{parentName:"td"},'[{:key "key" :value "value"}]'))))),(0,l.kt)("p",null,(0,l.kt)("strong",{parentName:"p"},"Note on errors:"),"\nSerialize will throw error in following cases"),(0,l.kt)("ol",null,(0,l.kt)("li",{parentName:"ol"},"unknown field is passed that's not present in schema ",(0,l.kt)("inlineCode",{parentName:"li"},"{:cause :unknown-field :info {:field-name }}")),(0,l.kt)("li",{parentName:"ol"},"if non-collection type is passed to repeated field ",(0,l.kt)("inlineCode",{parentName:"li"},"{:cause :not-a-collection :info {:value }}")),(0,l.kt)("li",{parentName:"ol"},"If unknown enum value passed that's not present in schema ",(0,l.kt)("inlineCode",{parentName:"li"},"{:cause :unknown-enum-value :info {:field-name }}"))),(0,l.kt)("h2",{id:"api"},"API"),(0,l.kt)("ul",null,(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("p",{parentName:"li"},(0,l.kt)("inlineCode",{parentName:"p"},"create-client (client-config)")),(0,l.kt)("p",{parentName:"li"},"Returns a new Stencil Clojure client instance by passing client-config."),(0,l.kt)("h3",{parentName:"li",id:"client-config-structure-"},"Client config structure :"),(0,l.kt)("table",{parentName:"li"},(0,l.kt)("thead",{parentName:"table"},(0,l.kt)("tr",{parentName:"thead"},(0,l.kt)("th",{parentName:"tr",align:null},"Key"),(0,l.kt)("th",{parentName:"tr",align:null},"Type"),(0,l.kt)("th",{parentName:"tr",align:null},"Description"))),(0,l.kt)("tbody",{parentName:"table"},(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},"url")),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("em",{parentName:"td"},"String")),(0,l.kt)("td",{parentName:"tr",align:null},"Stencil url to fetch latest descriptor sets")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},"refresh-cache")),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("em",{parentName:"td"},"Boolean")),(0,l.kt)("td",{parentName:"tr",align:null},"Whether the cache should be refreshed or not")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},"refresh-ttl")),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("em",{parentName:"td"},"Integer")),(0,l.kt)("td",{parentName:"tr",align:null},"Cache TTL in minutes")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},"request-timeout")),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("em",{parentName:"td"},"Integer")),(0,l.kt)("td",{parentName:"tr",align:null},"Request timeout in milliseconds")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},"request-backoff-time")),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("em",{parentName:"td"},"Integer")),(0,l.kt)("td",{parentName:"tr",align:null},"Request back off time in minutes")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},"retry-count")),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("em",{parentName:"td"},"Integer")),(0,l.kt)("td",{parentName:"tr",align:null},"Number of retries to be made to fetch descriptor sets")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},"headers")),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("em",{parentName:"td"},"Map")),(0,l.kt)("td",{parentName:"tr",align:null},"Map with key as header key and value as header value, which will be passed to stencil server")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},"refresh-strategy")),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("em",{parentName:"td"},"keyword")),(0,l.kt)("td",{parentName:"tr",align:null},"Possible values :version-based-refresh, :long-polling-refresh. Default :long-polling-refresh")))),(0,l.kt)("p",{parentName:"li"},"Example:"),(0,l.kt)("pre",{parentName:"li"},(0,l.kt)("code",{parentName:"pre",className:"language-clojure"},' (let [sample-client-config {:url "https://example-url"\n :refresh-cache true\n :refresh-ttl 100\n :request-timeout 10000\n :request-backoff-time 100\n :retry-count 3\n :headers {"Authorization" "Bearer "}\n :refresh-strategy :version-based-refresh\n }]\n (create-client sample-client-config))\n'))),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("p",{parentName:"li"},(0,l.kt)("inlineCode",{parentName:"p"},"get-descriptor (client proto-class-name)")),(0,l.kt)("p",{parentName:"li"},"Returns protobuf descriptor object for the given protobuf class name."),(0,l.kt)("h3",{parentName:"li",id:"argument-list-"},"Argument list :"),(0,l.kt)("table",{parentName:"li"},(0,l.kt)("thead",{parentName:"table"},(0,l.kt)("tr",{parentName:"thead"},(0,l.kt)("th",{parentName:"tr",align:null},"Key"),(0,l.kt)("th",{parentName:"tr",align:null},"Type"),(0,l.kt)("th",{parentName:"tr",align:null},"Description"))),(0,l.kt)("tbody",{parentName:"table"},(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},"client")),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("em",{parentName:"td"},"Object")),(0,l.kt)("td",{parentName:"tr",align:null},"Instantiated Clojure client object")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},"proto-class-name")),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("em",{parentName:"td"},"String")),(0,l.kt)("td",{parentName:"tr",align:null},"Name of the proto class whose proto descriptor object is required")))),(0,l.kt)("h3",{parentName:"li",id:"response-structure"},"Response structure"),(0,l.kt)("table",{parentName:"li"},(0,l.kt)("thead",{parentName:"table"},(0,l.kt)("tr",{parentName:"thead"},(0,l.kt)("th",{parentName:"tr",align:null},"Value"),(0,l.kt)("th",{parentName:"tr",align:null},"Type"),(0,l.kt)("th",{parentName:"tr",align:null},"Description"))),(0,l.kt)("tbody",{parentName:"table"},(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("strong",{parentName:"td"},"proto-desc")),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("em",{parentName:"td"},"Object")),(0,l.kt)("td",{parentName:"tr",align:null},"Protobuf descriptor for given proto class name")))),(0,l.kt)("p",{parentName:"li"},"Example:"),(0,l.kt)("pre",{parentName:"li"},(0,l.kt)("code",{parentName:"pre",className:"language-clojure"},'(let [client (create-client sample-client-config)\n proto-package "org.raystack.stencil_clj_test"\n proto-class-name "Scalar"\n fully-qualified-proto-name (str proto-package "." proto-class-name)]\n (get-descriptor client fully-qualified-proto-name))\n'))),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("p",{parentName:"li"},(0,l.kt)("inlineCode",{parentName:"p"},"deserialize (client proto-class-name data)")),(0,l.kt)("p",{parentName:"li"},"Returns Clojure map for the given protobuf encoded byte array and protobuf class name."),(0,l.kt)("h3",{parentName:"li",id:"argument-list--1"},"Argument list :"),(0,l.kt)("table",{parentName:"li"},(0,l.kt)("thead",{parentName:"table"},(0,l.kt)("tr",{parentName:"thead"},(0,l.kt)("th",{parentName:"tr",align:null},"Key"),(0,l.kt)("th",{parentName:"tr",align:null},"Type"),(0,l.kt)("th",{parentName:"tr",align:null},"Description"))),(0,l.kt)("tbody",{parentName:"table"},(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},"client")),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("em",{parentName:"td"},"Object")),(0,l.kt)("td",{parentName:"tr",align:null},"Instantiated Clojure client object")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},"proto-class-name")),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("em",{parentName:"td"},"String")),(0,l.kt)("td",{parentName:"tr",align:null},"Name of the proto class whose proto descriptor object is required")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},"data")),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("em",{parentName:"td"},"Byte-Array")),(0,l.kt)("td",{parentName:"tr",align:null},"Data (byte-array) to be deserialized using proto-descriptor object")))),(0,l.kt)("h3",{parentName:"li",id:"response-structure-1"},"Response structure"),(0,l.kt)("table",{parentName:"li"},(0,l.kt)("thead",{parentName:"table"},(0,l.kt)("tr",{parentName:"thead"},(0,l.kt)("th",{parentName:"tr",align:null},"Value"),(0,l.kt)("th",{parentName:"tr",align:null},"Type"),(0,l.kt)("th",{parentName:"tr",align:null},"Description"))),(0,l.kt)("tbody",{parentName:"table"},(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("strong",{parentName:"td"},"deserialized-message")),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("em",{parentName:"td"},"PersistentArrayMap")),(0,l.kt)("td",{parentName:"tr",align:null},"Deserialized message (Clojure Map)")))),(0,l.kt)("p",{parentName:"li"},"Example:"),(0,l.kt)("pre",{parentName:"li"},(0,l.kt)("code",{parentName:"pre",className:"language-clojure"},'(let [client (create-client sample-client-config)\n proto-package "org.raystack.stencil_clj_test"\n proto-class-name "Scalar"\n fully-qualified-proto-name (str proto-package "." proto-class-name)\n proto-desc (get-descriptor client fully-qualified-proto-name)\n data-to-deserialize (serialize client fully-qualified-proto-name{:field-one 1.25})]\n (deserialize client fully-qualified-proto-name data-to-deserialize))\n'))),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("p",{parentName:"li"},(0,l.kt)("inlineCode",{parentName:"p"},"serialize (client proto-class-name map)")),(0,l.kt)("p",{parentName:"li"},"Returns protobuf encoded byte array for the given Clojure and protobuf class name."),(0,l.kt)("h3",{parentName:"li",id:"argument-list--2"},"Argument list :"),(0,l.kt)("table",{parentName:"li"},(0,l.kt)("thead",{parentName:"table"},(0,l.kt)("tr",{parentName:"thead"},(0,l.kt)("th",{parentName:"tr",align:null},"Key"),(0,l.kt)("th",{parentName:"tr",align:null},"Type"),(0,l.kt)("th",{parentName:"tr",align:null},"Description"))),(0,l.kt)("tbody",{parentName:"table"},(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},"client")),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("em",{parentName:"td"},"Object")),(0,l.kt)("td",{parentName:"tr",align:null},"Instantiated Clojure client object")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},"proto-class-name")),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("em",{parentName:"td"},"String")),(0,l.kt)("td",{parentName:"tr",align:null},"Name of the proto class whose proto descriptor object is required")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},"map")),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("em",{parentName:"td"},"PersistentArrayMap")),(0,l.kt)("td",{parentName:"tr",align:null},"Data (in the form of map) to be serialized using proto descriptor object")))),(0,l.kt)("h3",{parentName:"li",id:"response-structure-2"},"Response structure"),(0,l.kt)("table",{parentName:"li"},(0,l.kt)("thead",{parentName:"table"},(0,l.kt)("tr",{parentName:"thead"},(0,l.kt)("th",{parentName:"tr",align:null},"Value"),(0,l.kt)("th",{parentName:"tr",align:null},"Type"),(0,l.kt)("th",{parentName:"tr",align:null},"Description"))),(0,l.kt)("tbody",{parentName:"table"},(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("strong",{parentName:"td"},"serialized-message")),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("em",{parentName:"td"},"Byte-Array")),(0,l.kt)("td",{parentName:"tr",align:null},"Serialized message (byte-array)")))),(0,l.kt)("p",{parentName:"li"},"Example:"),(0,l.kt)("pre",{parentName:"li"},(0,l.kt)("code",{parentName:"pre",className:"language-clojure"},'(let [client (create-client sample-client-config)\n proto-package "org.raystack.stencil_clj_test"\n proto-class-name "Scalar"\n fully-qualified-proto-name (str proto-package "." proto-class-name)\n proto-desc (get-descriptor client fully-qualified-proto-name)]\n (serialize client fully-qualified-proto-name {:field-one 1.25}))\n')))),(0,l.kt)("h2",{id:"development"},"Development"),(0,l.kt)("ul",null,(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("p",{parentName:"li"},"Ensure ",(0,l.kt)("a",{parentName:"p",href:"https://leiningen.org/"},"leiningen")," is installed.")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("p",{parentName:"li"},"Run tests: ",(0,l.kt)("inlineCode",{parentName:"p"},"lein clean && lein javac && lein test"))),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("p",{parentName:"li"},"Run formatting: ",(0,l.kt)("inlineCode",{parentName:"p"},"lein cljfmt fix")))))}c.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/935f2afb.888a9c11.js b/assets/js/935f2afb.836ced57.js similarity index 99% rename from assets/js/935f2afb.888a9c11.js rename to assets/js/935f2afb.836ced57.js index bdf74549..d6c4fad1 100644 --- a/assets/js/935f2afb.888a9c11.js +++ b/assets/js/935f2afb.836ced57.js @@ -1 +1 @@ -"use strict";(self.webpackChunkstencil=self.webpackChunkstencil||[]).push([[53],{1109:function(e){e.exports=JSON.parse('{"pluginId":"default","version":"current","label":"Next","banner":null,"badge":false,"className":"docs-version-current","isLast":true,"docsSidebars":{"docsSidebar":[{"type":"link","label":"Introduction","href":"/stencil/docs/introduction","docId":"introduction"},{"type":"link","label":"Usecases","href":"/stencil/docs/usecases","docId":"usecases"},{"type":"link","label":"Installation","href":"/stencil/docs/installation","docId":"installation"},{"type":"link","label":"Glossary","href":"/stencil/docs/glossary","docId":"glossary"},{"type":"category","label":"Guides","items":[{"type":"link","label":"Introduction","href":"/stencil/docs/guides/introduction","docId":"guides/introduction"},{"type":"link","label":"Quickstart","href":"/stencil/docs/guides/quickstart","docId":"guides/quickstart"},{"type":"link","label":"Manage namespaces","href":"/stencil/docs/guides/manage_namespace","docId":"guides/manage_namespace"},{"type":"link","label":"Manage schemas","href":"/stencil/docs/guides/manage_schemas","docId":"guides/manage_schemas"},{"type":"link","label":"Using clients","href":"/stencil/docs/guides/clients","docId":"guides/clients"}],"collapsed":true,"collapsible":true},{"type":"category","label":"Formats","items":[{"type":"link","label":"Protobuf","href":"/stencil/docs/formats/protobuf","docId":"formats/protobuf"},{"type":"link","label":"Avro","href":"/stencil/docs/formats/avro","docId":"formats/avro"},{"type":"link","label":"JSON","href":"/stencil/docs/formats/json","docId":"formats/json"}],"collapsed":true,"collapsible":true},{"type":"category","label":"Server","items":[{"type":"link","label":"Overview","href":"/stencil/docs/server/overview","docId":"server/overview"},{"type":"link","label":"Compatability rules","href":"/stencil/docs/server/rules","docId":"server/rules"}],"collapsed":true,"collapsible":true},{"type":"category","label":"Clients","items":[{"type":"link","label":"Overview","href":"/stencil/docs/clients/overview","docId":"clients/overview"},{"type":"link","label":"Go","href":"/stencil/docs/clients/go","docId":"clients/go"},{"type":"link","label":"Java","href":"/stencil/docs/clients/java","docId":"clients/java"},{"type":"link","label":"Clojure","href":"/stencil/docs/clients/clojure","docId":"clients/clojure"},{"type":"link","label":"JavaScript","href":"/stencil/docs/clients/js","docId":"clients/js"}],"collapsed":true,"collapsible":true},{"type":"category","label":"Reference","items":[{"type":"link","label":"API","href":"/stencil/docs/reference/api","docId":"reference/api"},{"type":"link","label":"CLI","href":"/stencil/docs/reference/cli","docId":"reference/cli"}],"collapsed":true,"collapsible":true},{"type":"category","label":"Contribute","items":[{"type":"link","label":"Contribution Process","href":"/stencil/docs/contribute/contribution","docId":"contribute/contribution"}],"collapsed":true,"collapsible":true},{"type":"link","label":"Roadmap","href":"/stencil/docs/roadmap","docId":"roadmap"}]},"docs":{"clients/clojure":{"id":"clients/clojure","title":"Clojure","description":"A Clojure library designed to easily encode and decode protobuf messages by using Clojure maps.","sidebar":"docsSidebar"},"clients/go":{"id":"clients/go","title":"Go","description":"Go Reference","sidebar":"docsSidebar"},"clients/java":{"id":"clients/java","title":"Java","description":"Stencil is dynamic schema registry for protobuf. Protobuf is a great efficient and fast mechanism for serializing structured data. The challenge with protobuf is that for every change it requires to recompile the package to generate the necessary classes. This is not a big challenge if you have protobuf enclosed in your application and compile at startup. But if you have thousands of protos stored in central registry and 100s of applications use them. Updating depndencies of compiled proto jar can soon become a nightmare.","sidebar":"docsSidebar"},"clients/js":{"id":"clients/js","title":"JavaScript","description":"Stencil nodejs client package provides a store to lookup protobuf descriptors and options to keep the protobuf descriptors upto date.","sidebar":"docsSidebar"},"clients/overview":{"id":"clients/overview","title":"Overview","description":"Stencil clients abstracts handling of descriptorset file on client side. Currently we officially support Stencil client in Java, Go, JS languages.","sidebar":"docsSidebar"},"contribute/contribution":{"id":"contribute/contribution","title":"Contribution Process","description":"The following is a set of guidelines for contributing to Stencil. These are mostly guidelines, not rules. Use your best judgment, and feel free to propose changes to this document in a pull request. Here are some important resources:","sidebar":"docsSidebar"},"formats/avro":{"id":"formats/avro","title":"Avro","description":"We are in the process of actively improving Stencil documentation. This guide will be updated very soon.","sidebar":"docsSidebar"},"formats/json":{"id":"formats/json","title":"JSON","description":"We are in the process of actively improving Stencil documentation. This guide will be updated very soon.","sidebar":"docsSidebar"},"formats/protobuf":{"id":"formats/protobuf","title":"Protobuf","description":"We are in the process of actively improving Stencil documentation. This guide will be updated very soon.","sidebar":"docsSidebar"},"glossary":{"id":"glossary","title":"Glossary","description":"This section describes the core elements of a schema registry.","sidebar":"docsSidebar"},"guides/clients":{"id":"guides/clients","title":"Using clients","description":"","sidebar":"docsSidebar"},"guides/introduction":{"id":"guides/introduction","title":"Introduction","description":"This tour introduces you to Stencil schema registry. Along the way you will learn how to manage schemas, enforce rules, serialise and deserialise data using stencil clients.","sidebar":"docsSidebar"},"guides/manage_namespace":{"id":"guides/manage_namespace","title":"Manage namespaces","description":"We are in the process of actively improving Stencil documentation. This guide will be updated very soon.","sidebar":"docsSidebar"},"guides/manage_schemas":{"id":"guides/manage_schemas","title":"Manage schemas","description":"Create a schema","sidebar":"docsSidebar"},"guides/quickstart":{"id":"guides/quickstart","title":"Quickstart","description":"This quick start will explore how to use Stencil command line interface and client libraries inside your application code. As part of this quick start we will start stencil server, create schema and then use stencil clients to serialise and deserialise data using registered schemas.","sidebar":"docsSidebar"},"installation":{"id":"installation","title":"Installation","description":"Stencil installation is simple. You can install Stencil on macOS, Windows, Linux, OpenBSD, FreeBSD, and on any machine. There are several approaches to installing Stencil.","sidebar":"docsSidebar"},"introduction":{"id":"introduction","title":"Introduction","description":"Welcome to intro guide to Stencil! This guide is the best place to start with Stencil. We cover what Stencil is, what problems it can solve, how it compares to existing schema registry, and how you can get started using it. If you are familiar with the basics of Stencil, the guide provides a more detailed reference of available features.","sidebar":"docsSidebar"},"reference/api":{"id":"reference/api","title":"API","description":"Version: 0.5.0","sidebar":"docsSidebar"},"reference/cli":{"id":"reference/cli","title":"CLI","description":"stencil completion [bash|zsh|fish|powershell]","sidebar":"docsSidebar"},"roadmap":{"id":"roadmap","title":"Roadmap","description":"","sidebar":"docsSidebar"},"server/overview":{"id":"server/overview","title":"Overview","description":"Stencil is dynamic protobuf schema registry. It provides REST interface for storing and retrieving protobuf file descriptors.","sidebar":"docsSidebar"},"server/rules":{"id":"server/rules","title":"Compatability rules","description":"Stencil server provides following compatibility rules.","sidebar":"docsSidebar"},"usecases":{"id":"usecases","title":"Usecases","description":"This page describes popular Stencil use cases and provides related resources that you can use to create Stencil workflows.","sidebar":"docsSidebar"}}}')}}]); \ No newline at end of file +"use strict";(self.webpackChunkstencil=self.webpackChunkstencil||[]).push([[53],{1109:function(e){e.exports=JSON.parse('{"pluginId":"default","version":"current","label":"Next","banner":null,"badge":false,"className":"docs-version-current","isLast":true,"docsSidebars":{"docsSidebar":[{"type":"link","label":"Introduction","href":"/stencil/docs/introduction","docId":"introduction"},{"type":"link","label":"Usecases","href":"/stencil/docs/usecases","docId":"usecases"},{"type":"link","label":"Installation","href":"/stencil/docs/installation","docId":"installation"},{"type":"link","label":"Glossary","href":"/stencil/docs/glossary","docId":"glossary"},{"type":"category","label":"Guides","items":[{"type":"link","label":"Introduction","href":"/stencil/docs/guides/introduction","docId":"guides/introduction"},{"type":"link","label":"Quickstart","href":"/stencil/docs/guides/quickstart","docId":"guides/quickstart"},{"type":"link","label":"Manage namespaces","href":"/stencil/docs/guides/manage_namespace","docId":"guides/manage_namespace"},{"type":"link","label":"Manage schemas","href":"/stencil/docs/guides/manage_schemas","docId":"guides/manage_schemas"},{"type":"link","label":"Using clients","href":"/stencil/docs/guides/clients","docId":"guides/clients"}],"collapsed":true,"collapsible":true},{"type":"category","label":"Formats","items":[{"type":"link","label":"Protobuf","href":"/stencil/docs/formats/protobuf","docId":"formats/protobuf"},{"type":"link","label":"Avro","href":"/stencil/docs/formats/avro","docId":"formats/avro"},{"type":"link","label":"JSON","href":"/stencil/docs/formats/json","docId":"formats/json"}],"collapsed":true,"collapsible":true},{"type":"category","label":"Server","items":[{"type":"link","label":"Overview","href":"/stencil/docs/server/overview","docId":"server/overview"},{"type":"link","label":"Compatability rules","href":"/stencil/docs/server/rules","docId":"server/rules"}],"collapsed":true,"collapsible":true},{"type":"category","label":"Clients","items":[{"type":"link","label":"Overview","href":"/stencil/docs/clients/overview","docId":"clients/overview"},{"type":"link","label":"Go","href":"/stencil/docs/clients/go","docId":"clients/go"},{"type":"link","label":"Java","href":"/stencil/docs/clients/java","docId":"clients/java"},{"type":"link","label":"Clojure","href":"/stencil/docs/clients/clojure","docId":"clients/clojure"},{"type":"link","label":"JavaScript","href":"/stencil/docs/clients/js","docId":"clients/js"}],"collapsed":true,"collapsible":true},{"type":"category","label":"Reference","items":[{"type":"link","label":"API","href":"/stencil/docs/reference/api","docId":"reference/api"},{"type":"link","label":"CLI","href":"/stencil/docs/reference/cli","docId":"reference/cli"}],"collapsed":true,"collapsible":true},{"type":"category","label":"Contribute","items":[{"type":"link","label":"Contribution Process","href":"/stencil/docs/contribute/contribution","docId":"contribute/contribution"}],"collapsed":true,"collapsible":true},{"type":"link","label":"Roadmap","href":"/stencil/docs/roadmap","docId":"roadmap"}]},"docs":{"clients/clojure":{"id":"clients/clojure","title":"Clojure","description":"A Clojure library designed to easily encode and decode protobuf messages by using Clojure maps.","sidebar":"docsSidebar"},"clients/go":{"id":"clients/go","title":"Go","description":"Go Reference","sidebar":"docsSidebar"},"clients/java":{"id":"clients/java","title":"Java","description":"Stencil is dynamic schema registry for protobuf. Protobuf is a great efficient and fast mechanism for serializing structured data. The challenge with protobuf is that for every change it requires to recompile the package to generate the necessary classes. This is not a big challenge if you have protobuf enclosed in your application and compile at startup. But if you have thousands of protos stored in central registry and 100s of applications use them. Updating depndencies of compiled proto jar can soon become a nightmare.","sidebar":"docsSidebar"},"clients/js":{"id":"clients/js","title":"JavaScript","description":"Stencil nodejs client package provides a store to lookup protobuf descriptors and options to keep the protobuf descriptors upto date.","sidebar":"docsSidebar"},"clients/overview":{"id":"clients/overview","title":"Overview","description":"Stencil clients abstracts handling of descriptorset file on client side. Currently we officially support Stencil client in Java, Go, JS languages.","sidebar":"docsSidebar"},"contribute/contribution":{"id":"contribute/contribution","title":"Contribution Process","description":"The following is a set of guidelines for contributing to Stencil. These are mostly guidelines, not rules. Use your best judgment, and feel free to propose changes to this document in a pull request. Here are some important resources:","sidebar":"docsSidebar"},"formats/avro":{"id":"formats/avro","title":"Avro","description":"We are in the process of actively improving Stencil documentation. This guide will be updated very soon.","sidebar":"docsSidebar"},"formats/json":{"id":"formats/json","title":"JSON","description":"We are in the process of actively improving Stencil documentation. This guide will be updated very soon.","sidebar":"docsSidebar"},"formats/protobuf":{"id":"formats/protobuf","title":"Protobuf","description":"We are in the process of actively improving Stencil documentation. This guide will be updated very soon.","sidebar":"docsSidebar"},"glossary":{"id":"glossary","title":"Glossary","description":"This section describes the core elements of a schema registry.","sidebar":"docsSidebar"},"guides/clients":{"id":"guides/clients","title":"Using clients","description":"","sidebar":"docsSidebar"},"guides/introduction":{"id":"guides/introduction","title":"Introduction","description":"This tour introduces you to Stencil schema registry. Along the way you will learn how to manage schemas, enforce rules, serialise and deserialise data using stencil clients.","sidebar":"docsSidebar"},"guides/manage_namespace":{"id":"guides/manage_namespace","title":"Manage namespaces","description":"We are in the process of actively improving Stencil documentation. This guide will be updated very soon.","sidebar":"docsSidebar"},"guides/manage_schemas":{"id":"guides/manage_schemas","title":"Manage schemas","description":"Create a schema","sidebar":"docsSidebar"},"guides/quickstart":{"id":"guides/quickstart","title":"Quickstart","description":"This quick start will explore how to use Stencil command line interface and client libraries inside your application code. As part of this quick start we will start stencil server, create schema and then use stencil clients to serialise and deserialise data using registered schemas.","sidebar":"docsSidebar"},"installation":{"id":"installation","title":"Installation","description":"Stencil installation is simple. You can install Stencil on macOS, Windows, Linux, OpenBSD, FreeBSD, and on any machine. There are several approaches to installing Stencil.","sidebar":"docsSidebar"},"introduction":{"id":"introduction","title":"Introduction","description":"Welcome to intro guide to Stencil! This guide is the best place to start with Stencil. We cover what Stencil is, what problems it can solve, how it compares to existing schema registry, and how you can get started using it. If you are familiar with the basics of Stencil, the guide provides a more detailed reference of available features.","sidebar":"docsSidebar"},"reference/api":{"id":"reference/api","title":"API","description":"Version: 0.5.1","sidebar":"docsSidebar"},"reference/cli":{"id":"reference/cli","title":"CLI","description":"stencil completion [bash|zsh|fish|powershell]","sidebar":"docsSidebar"},"roadmap":{"id":"roadmap","title":"Roadmap","description":"","sidebar":"docsSidebar"},"server/overview":{"id":"server/overview","title":"Overview","description":"Stencil is dynamic protobuf schema registry. It provides REST interface for storing and retrieving protobuf file descriptors.","sidebar":"docsSidebar"},"server/rules":{"id":"server/rules","title":"Compatability rules","description":"Stencil server provides following compatibility rules.","sidebar":"docsSidebar"},"usecases":{"id":"usecases","title":"Usecases","description":"This page describes popular Stencil use cases and provides related resources that you can use to create Stencil workflows.","sidebar":"docsSidebar"}}}')}}]); \ No newline at end of file diff --git a/assets/js/b95ea484.8b084b90.js b/assets/js/b95ea484.4ba231ae.js similarity index 99% rename from assets/js/b95ea484.8b084b90.js rename to assets/js/b95ea484.4ba231ae.js index 1fd974c6..a2c5c57e 100644 --- a/assets/js/b95ea484.8b084b90.js +++ b/assets/js/b95ea484.4ba231ae.js @@ -1 +1 @@ -"use strict";(self.webpackChunkstencil=self.webpackChunkstencil||[]).push([[488],{3905:function(t,e,a){a.d(e,{Zo:function(){return d},kt:function(){return N}});var n=a(7294);function l(t,e,a){return e in t?Object.defineProperty(t,e,{value:a,enumerable:!0,configurable:!0,writable:!0}):t[e]=a,t}function r(t,e){var a=Object.keys(t);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(t);e&&(n=n.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),a.push.apply(a,n)}return a}function p(t){for(var e=1;e=0||(l[a]=t[a]);return l}(t,e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(t);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(t,a)&&(l[a]=t[a])}return l}var i=n.createContext({}),s=function(t){var e=n.useContext(i),a=e;return t&&(a="function"==typeof t?t(e):p(p({},e),t)),a},d=function(t){var e=s(t.components);return n.createElement(i.Provider,{value:e},t.children)},k={inlineCode:"code",wrapper:function(t){var e=t.children;return n.createElement(n.Fragment,{},e)}},u=n.forwardRef((function(t,e){var a=t.components,l=t.mdxType,r=t.originalType,i=t.parentName,d=m(t,["components","mdxType","originalType","parentName"]),u=s(a),N=l,o=u["".concat(i,".").concat(N)]||u[N]||k[N]||r;return a?n.createElement(o,p(p({ref:e},d),{},{components:a})):n.createElement(o,p({ref:e},d))}));function N(t,e){var a=arguments,l=e&&e.mdxType;if("string"==typeof t||l){var r=a.length,p=new Array(r);p[0]=u;var m={};for(var i in e)hasOwnProperty.call(e,i)&&(m[i]=e[i]);m.originalType=t,m.mdxType="string"==typeof t?t:l,p[1]=m;for(var s=2;s=0||(l[a]=t[a]);return l}(t,e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(t);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(t,a)&&(l[a]=t[a])}return l}var i=n.createContext({}),s=function(t){var e=n.useContext(i),a=e;return t&&(a="function"==typeof t?t(e):p(p({},e),t)),a},d=function(t){var e=s(t.components);return n.createElement(i.Provider,{value:e},t.children)},k={inlineCode:"code",wrapper:function(t){var e=t.children;return n.createElement(n.Fragment,{},e)}},u=n.forwardRef((function(t,e){var a=t.components,l=t.mdxType,r=t.originalType,i=t.parentName,d=m(t,["components","mdxType","originalType","parentName"]),u=s(a),N=l,o=u["".concat(i,".").concat(N)]||u[N]||k[N]||r;return a?n.createElement(o,p(p({ref:e},d),{},{components:a})):n.createElement(o,p({ref:e},d))}));function N(t,e){var a=arguments,l=e&&e.mdxType;if("string"==typeof t||l){var r=a.length,p=new Array(r);p[0]=u;var m={};for(var i in e)hasOwnProperty.call(e,i)&&(m[i]=e[i]);m.originalType=t,m.mdxType="string"==typeof t?t:l,p[1]=m;for(var s=2;s=r)&&Object.keys(o.O).every((function(e){return o.O[e](n[i])}))?n.splice(i--,1):(a=!1,r0&&e[d-1][2]>r;d--)e[d]=e[d-1];e[d]=[n,f,r]},o.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return o.d(t,{a:t}),t},n=Object.getPrototypeOf?function(e){return Object.getPrototypeOf(e)}:function(e){return e.__proto__},o.t=function(e,f){if(1&f&&(e=this(e)),8&f)return e;if("object"==typeof e&&e){if(4&f&&e.__esModule)return e;if(16&f&&"function"==typeof e.then)return e}var r=Object.create(null);o.r(r);var c={};t=t||[null,n({}),n([]),n(n)];for(var a=2&f&&e;"object"==typeof a&&!~t.indexOf(a);a=n(a))Object.getOwnPropertyNames(a).forEach((function(t){c[t]=function(){return e[t]}}));return c.default=function(){return e},o.d(r,c),r},o.d=function(e,t){for(var n in t)o.o(t,n)&&!o.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},o.f={},o.e=function(e){return Promise.all(Object.keys(o.f).reduce((function(t,n){return o.f[n](e,t),t}),[]))},o.u=function(e){return"assets/js/"+({13:"01a85c17",41:"13d4530b",53:"935f2afb",58:"598ef0fd",59:"07cbf940",75:"0dffb83e",89:"a6aa9e1f",93:"2d612599",103:"ccc49370",128:"a09c2993",149:"274771d6",157:"87ef627e",165:"194ba4b8",186:"a7e2f087",195:"c4f5d8e4",206:"1c35425d",217:"3b8c55ea",225:"131e72b5",251:"9f3d9755",291:"e747ec83",383:"91b39d10",403:"f3275a05",413:"1fd6179b",488:"b95ea484",514:"1be78505",517:"2fe47422",535:"814f3328",556:"f95a9f4f",608:"9e4087bc",610:"6875c492",614:"690cf7c6",713:"18cda328",740:"7e37206e",777:"79473a12",792:"e1a0e8c5",794:"caf67d42",841:"06b9d165",849:"b6712a1c",918:"17896441",930:"ba375c2b",958:"b1016243",960:"91c76d4c",998:"941c2db8"}[e]||e)+"."+{13:"f333ef9a",41:"5d88f6cd",53:"888a9c11",58:"bff91fe8",59:"765ba63b",75:"da6bcbb7",89:"12c1c25f",93:"f19bf97f",103:"86379386",128:"ed6dd5b5",149:"a767e191",157:"73a194bf",165:"eccbd1f6",186:"9c4392ee",195:"a7a998e6",206:"4228498e",217:"2891c04d",225:"c6168c19",251:"85bb24eb",291:"8416d63a",383:"73064f29",403:"053ff962",413:"ed1ac88a",488:"8b084b90",514:"35460903",517:"e7270f7a",535:"5d10e57d",556:"9073f231",608:"833962f4",610:"d39b1e87",614:"b08a952e",713:"d5a82d99",740:"fdaa8fd3",777:"b6d23362",792:"5f578c92",794:"d7a63519",818:"608b18fc",841:"282d7f3b",849:"90194d13",897:"137fbd33",918:"98656941",930:"f16a090b",958:"34e095f3",960:"4fd32fa7",998:"4341b5db"}[e]+".js"},o.miniCssF=function(e){},o.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),o.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},f={},r="stencil:",o.l=function(e,t,n,c){if(f[e])f[e].push(t);else{var a,i;if(void 0!==n)for(var u=document.getElementsByTagName("script"),d=0;d=r)&&Object.keys(o.O).every((function(e){return o.O[e](n[i])}))?n.splice(i--,1):(a=!1,r0&&e[d-1][2]>r;d--)e[d]=e[d-1];e[d]=[n,f,r]},o.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return o.d(t,{a:t}),t},n=Object.getPrototypeOf?function(e){return Object.getPrototypeOf(e)}:function(e){return e.__proto__},o.t=function(e,f){if(1&f&&(e=this(e)),8&f)return e;if("object"==typeof e&&e){if(4&f&&e.__esModule)return e;if(16&f&&"function"==typeof e.then)return e}var r=Object.create(null);o.r(r);var c={};t=t||[null,n({}),n([]),n(n)];for(var a=2&f&&e;"object"==typeof a&&!~t.indexOf(a);a=n(a))Object.getOwnPropertyNames(a).forEach((function(t){c[t]=function(){return e[t]}}));return c.default=function(){return e},o.d(r,c),r},o.d=function(e,t){for(var n in t)o.o(t,n)&&!o.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},o.f={},o.e=function(e){return Promise.all(Object.keys(o.f).reduce((function(t,n){return o.f[n](e,t),t}),[]))},o.u=function(e){return"assets/js/"+({13:"01a85c17",41:"13d4530b",53:"935f2afb",58:"598ef0fd",59:"07cbf940",75:"0dffb83e",89:"a6aa9e1f",93:"2d612599",103:"ccc49370",128:"a09c2993",149:"274771d6",157:"87ef627e",165:"194ba4b8",186:"a7e2f087",195:"c4f5d8e4",206:"1c35425d",217:"3b8c55ea",225:"131e72b5",251:"9f3d9755",291:"e747ec83",383:"91b39d10",403:"f3275a05",413:"1fd6179b",488:"b95ea484",514:"1be78505",517:"2fe47422",535:"814f3328",556:"f95a9f4f",608:"9e4087bc",610:"6875c492",614:"690cf7c6",713:"18cda328",740:"7e37206e",777:"79473a12",792:"e1a0e8c5",794:"caf67d42",841:"06b9d165",849:"b6712a1c",918:"17896441",930:"ba375c2b",958:"b1016243",960:"91c76d4c",998:"941c2db8"}[e]||e)+"."+{13:"f333ef9a",41:"5d88f6cd",53:"836ced57",58:"d650532f",59:"765ba63b",75:"da6bcbb7",89:"12c1c25f",93:"f19bf97f",103:"86379386",128:"ed6dd5b5",149:"a767e191",157:"73a194bf",165:"eccbd1f6",186:"9c4392ee",195:"a7a998e6",206:"4228498e",217:"f0595028",225:"c6168c19",251:"85bb24eb",291:"8416d63a",383:"73064f29",403:"053ff962",413:"ed1ac88a",488:"4ba231ae",514:"35460903",517:"e7270f7a",535:"5d10e57d",556:"9073f231",608:"833962f4",610:"d39b1e87",614:"8e8fce2d",713:"d5a82d99",740:"fdaa8fd3",777:"b6d23362",792:"5f578c92",794:"d7a63519",818:"608b18fc",841:"282d7f3b",849:"90194d13",897:"137fbd33",918:"98656941",930:"f16a090b",958:"34e095f3",960:"4fd32fa7",998:"4341b5db"}[e]+".js"},o.miniCssF=function(e){},o.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),o.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},f={},r="stencil:",o.l=function(e,t,n,c){if(f[e])f[e].push(t);else{var a,i;if(void 0!==n)for(var u=document.getElementsByTagName("script"),d=0;d Archive | Stencil - +
- + \ No newline at end of file diff --git a/blog/index.html b/blog/index.html index 8778cdb3..d8cedd6e 100644 --- a/blog/index.html +++ b/blog/index.html @@ -10,13 +10,13 @@ Blog | Stencil - +
- + \ No newline at end of file diff --git a/blog/introducing-stencil/index.html b/blog/introducing-stencil/index.html index f3be1909..d32be971 100644 --- a/blog/introducing-stencil/index.html +++ b/blog/introducing-stencil/index.html @@ -10,13 +10,13 @@ Introducing Stencil | Stencil - +
- + \ No newline at end of file diff --git a/blog/tags/index.html b/blog/tags/index.html index ec90edfc..d4a705df 100644 --- a/blog/tags/index.html +++ b/blog/tags/index.html @@ -10,13 +10,13 @@ Tags | Stencil - +
- + \ No newline at end of file diff --git a/blog/tags/raystack/index.html b/blog/tags/raystack/index.html index b4c672e8..33d38290 100644 --- a/blog/tags/raystack/index.html +++ b/blog/tags/raystack/index.html @@ -10,13 +10,13 @@ One post tagged with "raystack" | Stencil - +

One post tagged with "raystack"

View All Tags
- + \ No newline at end of file diff --git a/blog/tags/stencil/index.html b/blog/tags/stencil/index.html index e7a34267..5545aa0a 100644 --- a/blog/tags/stencil/index.html +++ b/blog/tags/stencil/index.html @@ -10,13 +10,13 @@ One post tagged with "stencil" | Stencil - +

One post tagged with "stencil"

View All Tags
- + \ No newline at end of file diff --git a/docs/clients/clojure/index.html b/docs/clients/clojure/index.html index 18f5f35d..93393213 100644 --- a/docs/clients/clojure/index.html +++ b/docs/clients/clojure/index.html @@ -10,14 +10,14 @@ Clojure | Stencil - +
-

Clojure

A Clojure library designed to easily encode and decode protobuf messages by using Clojure maps.

Installation

Add the below dependency to your project.clj file:

[org.raystack/stencil-clj "0.4.1"]

Usage

Consider following proto message

syntax = "proto3";

package example;

option java_multiple_files = true;
option java_package = "org.raystack.CljTest";

message Address {
string city = 1;
string street = 2;
}

message Person {
enum Gender {
UNKNOWN = 0;
MALE = 1;
FEMALE = 2;
NON_BINARY = 3;
}
string name = 1;
Address address = 2;
Gender gender = 3;
repeated string email_list = 4;
int32 age = 5;
}
  1. Create stencil client. You can refer to java client documentation for all available options.
(ns test
(:require [stencil.core :refer [create-client]]))

(def client (create-client {:url "<stencil service url>"
:refresh-cache true
:refresh-strategy :version-based-refresh
:headers {"<headerkey>" "<header value>"}))
  1. To serialize data from clojure map
(:require [stencil.core :refer [serialize]])

(def serialized-data
(serialize client "org.raystack.CljTest" {:name "Foo"
:address {:street "bar"}
:email-list ["a@example.com" "b@b.com"]
:gender :NON-BINARY
:age 10}))
  1. Deserialize data from bytes to clojure map
(:require [stencil.core :refer [deserialize]])

(deserialize client "org.raystack.CljTest" serialized-data)
;; prints
;; {:name "Foo"
;; :address {:street "bar"}
;; :email-list ["a@example.com" "b@b.com"]
;; :gender :NON-BINARY
;; :age 10}

Protocol buffers - Clojure interop

ProtobufClojureNotes
field nameskeywords in kebab casename -> :name, field_name -> :field-name
scalar fieldsValues follow protobuf-java scalar value mappings
enumsValues converted as keywords of enum's original valueUNKNOWN -> :UNKNOWN
messagesclojure mapmessage Hello {string name = 1;} -> {:name "raystack"}
repeated fieldsclojure vector
one-of fieldstreated as regular fieldsif two fields are set that are part of one-of, last seen value is considered while serializing data
mapmap values follow it's wire representationfor map<string, string> type, example value will be [{:key "key" :value "value"}]

Note on errors: +

Clojure

A Clojure library designed to easily encode and decode protobuf messages by using Clojure maps.

Installation

Add the below dependency to your project.clj file:

[org.raystack/stencil-clj "0.5.1"]

Usage

Consider following proto message

syntax = "proto3";

package example;

option java_multiple_files = true;
option java_package = "org.raystack.CljTest";

message Address {
string city = 1;
string street = 2;
}

message Person {
enum Gender {
UNKNOWN = 0;
MALE = 1;
FEMALE = 2;
NON_BINARY = 3;
}
string name = 1;
Address address = 2;
Gender gender = 3;
repeated string email_list = 4;
int32 age = 5;
}
  1. Create stencil client. You can refer to java client documentation for all available options.
(ns test
(:require [stencil.core :refer [create-client]]))

(def client (create-client {:url "<stencil service url>"
:refresh-cache true
:refresh-strategy :version-based-refresh
:headers {"<headerkey>" "<header value>"}))
  1. To serialize data from clojure map
(:require [stencil.core :refer [serialize]])

(def serialized-data
(serialize client "org.raystack.CljTest" {:name "Foo"
:address {:street "bar"}
:email-list ["a@example.com" "b@b.com"]
:gender :NON-BINARY
:age 10}))
  1. Deserialize data from bytes to clojure map
(:require [stencil.core :refer [deserialize]])

(deserialize client "org.raystack.CljTest" serialized-data)
;; prints
;; {:name "Foo"
;; :address {:street "bar"}
;; :email-list ["a@example.com" "b@b.com"]
;; :gender :NON-BINARY
;; :age 10}

Protocol buffers - Clojure interop

ProtobufClojureNotes
field nameskeywords in kebab casename -> :name, field_name -> :field-name
scalar fieldsValues follow protobuf-java scalar value mappings
enumsValues converted as keywords of enum's original valueUNKNOWN -> :UNKNOWN
messagesclojure mapmessage Hello {string name = 1;} -> {:name "raystack"}
repeated fieldsclojure vector
one-of fieldstreated as regular fieldsif two fields are set that are part of one-of, last seen value is considered while serializing data
mapmap values follow it's wire representationfor map<string, string> type, example value will be [{:key "key" :value "value"}]

Note on errors: Serialize will throw error in following cases

  1. unknown field is passed that's not present in schema {:cause :unknown-field :info {:field-name <field-name>}}
  2. if non-collection type is passed to repeated field {:cause :not-a-collection :info {:value <value>}}
  3. If unknown enum value passed that's not present in schema {:cause :unknown-enum-value :info {:field-name <field-name>}}

API

  • create-client (client-config)

    Returns a new Stencil Clojure client instance by passing client-config.

    Client config structure :

    KeyTypeDescription
    urlStringStencil url to fetch latest descriptor sets
    refresh-cacheBooleanWhether the cache should be refreshed or not
    refresh-ttlIntegerCache TTL in minutes
    request-timeoutIntegerRequest timeout in milliseconds
    request-backoff-timeIntegerRequest back off time in minutes
    retry-countIntegerNumber of retries to be made to fetch descriptor sets
    headersMapMap with key as header key and value as header value, which will be passed to stencil server
    refresh-strategykeywordPossible values :version-based-refresh, :long-polling-refresh. Default :long-polling-refresh

    Example:

     (let [sample-client-config {:url       "https://example-url"
    :refresh-cache true
    :refresh-ttl 100
    :request-timeout 10000
    :request-backoff-time 100
    :retry-count 3
    :headers {"Authorization" "Bearer <token>"}
    :refresh-strategy :version-based-refresh
    }]
    (create-client sample-client-config))
  • get-descriptor (client proto-class-name)

    Returns protobuf descriptor object for the given protobuf class name.

    Argument list :

    KeyTypeDescription
    clientObjectInstantiated Clojure client object
    proto-class-nameStringName of the proto class whose proto descriptor object is required

    Response structure

    ValueTypeDescription
    proto-descObjectProtobuf descriptor for given proto class name

    Example:

    (let [client (create-client sample-client-config)
    proto-package "org.raystack.stencil_clj_test"
    proto-class-name "Scalar"
    fully-qualified-proto-name (str proto-package "." proto-class-name)]
    (get-descriptor client fully-qualified-proto-name))
  • deserialize (client proto-class-name data)

    Returns Clojure map for the given protobuf encoded byte array and protobuf class name.

    Argument list :

    KeyTypeDescription
    clientObjectInstantiated Clojure client object
    proto-class-nameStringName of the proto class whose proto descriptor object is required
    dataByte-ArrayData (byte-array) to be deserialized using proto-descriptor object

    Response structure

    ValueTypeDescription
    deserialized-messagePersistentArrayMapDeserialized message (Clojure Map)

    Example:

    (let [client (create-client sample-client-config)
    proto-package "org.raystack.stencil_clj_test"
    proto-class-name "Scalar"
    fully-qualified-proto-name (str proto-package "." proto-class-name)
    proto-desc (get-descriptor client fully-qualified-proto-name)
    data-to-deserialize (serialize client fully-qualified-proto-name{:field-one 1.25})]
    (deserialize client fully-qualified-proto-name data-to-deserialize))
  • serialize (client proto-class-name map)

    Returns protobuf encoded byte array for the given Clojure and protobuf class name.

    Argument list :

    KeyTypeDescription
    clientObjectInstantiated Clojure client object
    proto-class-nameStringName of the proto class whose proto descriptor object is required
    mapPersistentArrayMapData (in the form of map) to be serialized using proto descriptor object

    Response structure

    ValueTypeDescription
    serialized-messageByte-ArraySerialized message (byte-array)

    Example:

    (let [client (create-client sample-client-config)
    proto-package "org.raystack.stencil_clj_test"
    proto-class-name "Scalar"
    fully-qualified-proto-name (str proto-package "." proto-class-name)
    proto-desc (get-descriptor client fully-qualified-proto-name)]
    (serialize client fully-qualified-proto-name {:field-one 1.25}))

Development

  • Ensure leiningen is installed.

  • Run tests: lein clean && lein javac && lein test

  • Run formatting: lein cljfmt fix

- + \ No newline at end of file diff --git a/docs/clients/go/index.html b/docs/clients/go/index.html index 02faa1f1..b9730c77 100644 --- a/docs/clients/go/index.html +++ b/docs/clients/go/index.html @@ -10,13 +10,13 @@ Go | Stencil - +

Go

Go Reference

Stencil go client package provides a store to lookup protobuf descriptors and options to keep the protobuf descriptors upto date.

It has following features

  • Deserialize protobuf messages directly by specifying protobuf message name
  • Serialize data by specifying protobuf message name
  • Ability to refresh protobuf descriptors in specified intervals
  • Support to download descriptors from multiple urls

Requirements

  • go 1.16

Installation

Use go get

go get github.com/raystack/stencil/clients/go

Then import the stencil package into your own code as mentioned below

import stencil "github.com/raystack/stencil/clients/go"

Usage

Creating a client

import stencil "github.com/raystack/stencil/clients/go"

url := "http://localhost:8000/v1beta1/namespaces/{test-namespace}/schemas/{schema-name}"
client, err := stencil.NewClient([]string{url}, stencil.Options{})

Get Descriptor

import stencil "github.com/raystack/stencil/clients/go"

url := "http://localhost:8000/v1beta1/namespaces/{test-namespace}/schemas/{schema-name}"
client, err := stencil.NewClient([]string{url}, stencil.Options{})
if err != nil {
return
}
desc, err := client.GetDescriptor("google.protobuf.DescriptorProto")

Parse protobuf message.

import stencil "github.com/raystack/stencil/clients/go"

url := "http://localhost:8000/v1beta1/namespaces/{test-namespace}/schemas/{schema-name}"
client, err := stencil.NewClient([]string{url}, stencil.Options{})
if err != nil {
return
}
data := []byte("")
parsedMsg, err := client.Parse("google.protobuf.DescriptorProto", data)

Serialize data.

import stencil "github.com/raystack/stencil/clients/go"

url := "http://url/to/proto/descriptorset/file"
client, err := stencil.NewClient([]string{url}, stencil.Options{})
if err != nil {
return
}
data := map[string]interface{}{}
serializedMsg, err := client.Serialize("google.protobuf.DescriptorProto", data)

Enable auto refresh of schemas

import stencil "github.com/raystack/stencil/clients/go"

url := "http://localhost:8000/v1beta1/namespaces/{test-namespace}/schemas/{schema-name}"
// Configured to refresh schema every 12 hours
client, err := stencil.NewClient([]string{url}, stencil.Options{AutoRefresh: true, RefreshInterval: time.Hours * 12})
if err != nil {
return
}
desc, err := client.GetDescriptor("google.protobuf.DescriptorProto")

Using VersionBasedRefresh strategy

import stencil "github.com/raystack/stencil/clients/go"

url := "http://localhost:8000/v1beta1/namespaces/{test-namespace}/schemas/{schema-name}"
// Configured to refresh schema every 12 hours
client, err := stencil.NewClient([]string{url}, stencil.Options{AutoRefresh: true, RefreshInterval: time.Hours * 12, RefreshStrategy: stencil.VersionBasedRefresh})
if err != nil {
return
}
desc, err := client.GetDescriptor("google.protobuf.DescriptorProto")

Refer to go documentation for all available methods and options.

- + \ No newline at end of file diff --git a/docs/clients/java/index.html b/docs/clients/java/index.html index ccbdec09..dbf22cf7 100644 --- a/docs/clients/java/index.html +++ b/docs/clients/java/index.html @@ -10,13 +10,13 @@ Java | Stencil - +
-

Java

Stencil is dynamic schema registry for protobuf. Protobuf is a great efficient and fast mechanism for serializing structured data. The challenge with protobuf is that for every change it requires to recompile the package to generate the necessary classes. This is not a big challenge if you have protobuf enclosed in your application and compile at startup. But if you have thousands of protos stored in central registry and 100s of applications use them. Updating depndencies of compiled proto jar can soon become a nightmare.

Protobuf allows you to define a protobuf file using DescriptorSet. A FileDescriptorSet is basically a description of the proto file i.e. it’s name, it’s package name, it’s dependencies and the messages it contains. Once you have the descriptor file, you can simply read it in any language to create a FileDescriptor Object. Now any serialized ProtoMessage can be deserialized using DynamicMessage and ProtoMessage descriptor.

Requirements

Usage

Add stencil as dependency

Gradle

  implementation group: 'org.raystack', name: 'stencil', version: '0.5.0'

Maven

<dependency>
<groupId>org.raystack</groupId>
<artifactId>stencil</artifactId>
<version>0.5.0</version>
</dependency>

Creating a stencil Client instance

Stencil client can be created in different modes.

Loading Descriptor from Protobuf Class available in the classpath

import org.raystack.stencil.client.StencilClient;
import org.raystack.stencil.StencilClientFactory;

StencilClient stencilClient = StencilClientFactory.getClient();

Create client with remote URL

import org.raystack.stencil.config.StencilConfig;

String url = "http://url/to/proto/descriptor-set/file";
StencilClient stencilClient = StencilClientFacorty.getClient(url, StencilConfig.builder().build());

Creating MultiURL client

import org.raystack.stencil.config.StencilConfig;

ArrayList<String> urls = new ArrayList<String>();
urls.add("http://localhost:8082/v1beta1/...");
StencilClient stencilClient = StencilClientFacorty.getClient(urls, StencilConfig.builder().build());

With StatsD client for monitoring

// From https://github.com/tim-group/java-statsd-client
import com.timgroup.statsd.StatsDClient;
import com.timgroup.statsd.NonBlockingStatsDClient;

StatsDClient statDClient = new NonBlockingStatsDClient("my.prefix", "statsd-host", 8125);
StencilClient stencilClient = StencilClientFactory.getClient(url, StencilConfig.builder().statsDClient(statsDClient).build());

With Schema Update Listener

Whenever schema has changed this listener will be called.

import org.raystack.stencil.SchemaUpdateListener;

SchemaUpdateListener updateListener = new SchemaUpdateListenerImpl();
StencilClient stencilClient = StencilClientFactory.getClient(url, StencilConfig.builder().updateListener(updateListener).build());

With version based refresh strategy

If url belongs to stencil server, client can choose to refresh schema data only if there is a new version available.

import org.raystack.stencil.cache.SchemaRefreshStrategy;

StencilConfig config = StencilConfig.builder().refreshStrategy(SchemaRefreshStrategy.versionBasedRefresh()).build();
StencilClient stencilClient = StencilClientFactory.getClient(url, config);

Passing custom headers

While sending request to specified URL, client can be configured to pass headers as well.

import org.apache.http.Header;
import org.apache.http.HttpHeaders;
import org.apache.http.message.BasicHeader;

Header authHeader = new BasicHeader(HttpHeaders.AUTHORIZATION, "Bearer " + token);
List<Header> headers = new ArrayList<Header>();
headers.add(authHeader);
StencilConfig config = StencilConfig.builder().fetchHeaders(headers).build();
StencilClient stencilClient = StencilClientFactory.getClient(url, config);

Getting descriptor

Given the name of the Proto-Class StencilClient returns the Descriptor for it.

import com.google.protobuf.Descriptors;
import com.google.protobuf.DynamicMessage;

Descriptors.Descriptor descriptor = stencilClient.get(protoClassName);

Parsing message

import com.google.protobuf.Descriptors;
import com.google.protobuf.DynamicMessage;

Descriptors.Descriptor descriptor = stencilClient.get(protoClassName);
DynamicMessage message = DynamicMessage.parseFrom(descriptor, bytes);

Using Parser interface

import org.raystack.stencil.Parser;
import com.google.protobuf.DynamicMessage;

Parser protoParser = stencilClient.getParser("com.example.proto.schema");
DynamicMessage message = protoParser.parse(bytes)

Publishing

The client is published and released via github workflow and uses github tag for versioning.

Notes

  • Stencil uses java-statsd-client from com.timgroup, Please use the same client in your application for statsd
- +

Java

Stencil is dynamic schema registry for protobuf. Protobuf is a great efficient and fast mechanism for serializing structured data. The challenge with protobuf is that for every change it requires to recompile the package to generate the necessary classes. This is not a big challenge if you have protobuf enclosed in your application and compile at startup. But if you have thousands of protos stored in central registry and 100s of applications use them. Updating depndencies of compiled proto jar can soon become a nightmare.

Protobuf allows you to define a protobuf file using DescriptorSet. A FileDescriptorSet is basically a description of the proto file i.e. it’s name, it’s package name, it’s dependencies and the messages it contains. Once you have the descriptor file, you can simply read it in any language to create a FileDescriptor Object. Now any serialized ProtoMessage can be deserialized using DynamicMessage and ProtoMessage descriptor.

Requirements

Usage

Add stencil as dependency

Gradle

  implementation group: 'org.raystack', name: 'stencil', version: '0.5.1'

Maven

<dependency>
<groupId>org.raystack</groupId>
<artifactId>stencil</artifactId>
<version>0.5.1</version>
</dependency>

Creating a stencil Client instance

Stencil client can be created in different modes.

Loading Descriptor from Protobuf Class available in the classpath

import org.raystack.stencil.client.StencilClient;
import org.raystack.stencil.StencilClientFactory;

StencilClient stencilClient = StencilClientFactory.getClient();

Create client with remote URL

import org.raystack.stencil.config.StencilConfig;

String url = "http://url/to/proto/descriptor-set/file";
StencilClient stencilClient = StencilClientFacorty.getClient(url, StencilConfig.builder().build());

Creating MultiURL client

import org.raystack.stencil.config.StencilConfig;

ArrayList<String> urls = new ArrayList<String>();
urls.add("http://localhost:8082/v1beta1/...");
StencilClient stencilClient = StencilClientFacorty.getClient(urls, StencilConfig.builder().build());

With StatsD client for monitoring

// From https://github.com/tim-group/java-statsd-client
import com.timgroup.statsd.StatsDClient;
import com.timgroup.statsd.NonBlockingStatsDClient;

StatsDClient statDClient = new NonBlockingStatsDClient("my.prefix", "statsd-host", 8125);
StencilClient stencilClient = StencilClientFactory.getClient(url, StencilConfig.builder().statsDClient(statsDClient).build());

With Schema Update Listener

Whenever schema has changed this listener will be called.

import org.raystack.stencil.SchemaUpdateListener;

SchemaUpdateListener updateListener = new SchemaUpdateListenerImpl();
StencilClient stencilClient = StencilClientFactory.getClient(url, StencilConfig.builder().updateListener(updateListener).build());

With version based refresh strategy

If url belongs to stencil server, client can choose to refresh schema data only if there is a new version available.

import org.raystack.stencil.cache.SchemaRefreshStrategy;

StencilConfig config = StencilConfig.builder().refreshStrategy(SchemaRefreshStrategy.versionBasedRefresh()).build();
StencilClient stencilClient = StencilClientFactory.getClient(url, config);

Passing custom headers

While sending request to specified URL, client can be configured to pass headers as well.

import org.apache.http.Header;
import org.apache.http.HttpHeaders;
import org.apache.http.message.BasicHeader;

Header authHeader = new BasicHeader(HttpHeaders.AUTHORIZATION, "Bearer " + token);
List<Header> headers = new ArrayList<Header>();
headers.add(authHeader);
StencilConfig config = StencilConfig.builder().fetchHeaders(headers).build();
StencilClient stencilClient = StencilClientFactory.getClient(url, config);

Getting descriptor

Given the name of the Proto-Class StencilClient returns the Descriptor for it.

import com.google.protobuf.Descriptors;
import com.google.protobuf.DynamicMessage;

Descriptors.Descriptor descriptor = stencilClient.get(protoClassName);

Parsing message

import com.google.protobuf.Descriptors;
import com.google.protobuf.DynamicMessage;

Descriptors.Descriptor descriptor = stencilClient.get(protoClassName);
DynamicMessage message = DynamicMessage.parseFrom(descriptor, bytes);

Using Parser interface

import org.raystack.stencil.Parser;
import com.google.protobuf.DynamicMessage;

Parser protoParser = stencilClient.getParser("com.example.proto.schema");
DynamicMessage message = protoParser.parse(bytes)

Publishing

The client is published and released via github workflow and uses github tag for versioning.

Notes

  • Stencil uses java-statsd-client from com.timgroup, Please use the same client in your application for statsd
+ \ No newline at end of file diff --git a/docs/clients/js/index.html b/docs/clients/js/index.html index 33ea55b8..1ce294dc 100644 --- a/docs/clients/js/index.html +++ b/docs/clients/js/index.html @@ -10,13 +10,13 @@ JavaScript | Stencil - +

JavaScript

Stencil nodejs client package provides a store to lookup protobuf descriptors and options to keep the protobuf descriptors upto date.

It has following features

  • Ability to refresh protobuf descriptors in specified intervals
  • Support to download descriptors from multiple urls

Installation

npm install --save @raystack/stencil

Usage

Creating a client

const { Stencil } = require("stencil");

const url = "http://url/to/proto/descriptorset/file";
const client = await Stencil.getInstance(url, {
shouldRefresh: true,
refreshInterval: 43200, // 12 hrs
});

Creating a multiURLClient

const { MultiURLStencil } = require("stencil");

const url1 = "http://url/to/proto/descriptorset/file";
const url2 = "http://url/to/proto/descriptorset/file2";
const client = await MultiURLStencil.getInstance([url1, url2], {
shouldRefresh: true,
refreshInterval: 43200, // 12 hrs
});

Get proto descriptor type

const { Stencil } = require("stencil");

const url = "http://url/to/proto/descriptorset/file";
const client = await Stencil.getInstance(url, {
shouldRefresh: false,
});
const type = client.getType("google.protobuf.DescriptorProto");

Encode/Decode message

Let's say we want to encode message for below proto message defniniton

syntax = "proto3";

package test;

message One {
int64 field_one = 1;
}
const { Stencil } = require('stencil');

const url = 'http://url/to/proto/descriptorset/file';
const client = await Stencil.getInstance(url, {
shouldRefresh: false
});
const type = client.getType('test.One');
// Encode
const msg = { field_one: 10 };
const errs = type.verify(msg);
if errs {
throw new Error(`unable to serialize message: ${errs}`);
}
const encodedBuffer = type.encode(msg).finish();
// Decode
const decodedType = type.decode(encodedBuffer);
console.log(decodedType.toObject())

Setting up development environment

Prerequisite Tools

  1. Clone the repo

    $ git clone https://github.com/raystack/stencil
    $ cd stencil/clients/js
  2. Install dependencies

    $ npm install
  3. Run the tests. All of the tests are written with jest.

    $ npm test

Versioning

We use SemVer for versioning. For the versions available, see the tags.

- + \ No newline at end of file diff --git a/docs/clients/overview/index.html b/docs/clients/overview/index.html index e3115099..0c809241 100644 --- a/docs/clients/overview/index.html +++ b/docs/clients/overview/index.html @@ -10,13 +10,13 @@ Overview | Stencil - +

Overview

Stencil clients abstracts handling of descriptorset file on client side. Currently we officially support Stencil client in Java, Go, JS languages.

Features

  • downloading of descriptorset file from server
  • parse API to deserialize protobuf encoded messages
  • lookup API to find proto descriptors
  • inbuilt strategies to refresh protobuf schema definitions.

A note on configuring Stencil clients

  • Stencil server provides API to download latest descriptor file. If new version is available latest file will point to new descriptor file. Always use latest version proto descriptor url for stencil client if you want to refresh schema definitions in runtime.
  • Keep the refresh intervals relatively large (eg: 24hrs or 12 hrs) to reduce the number of calls depending on how fast systems produce new messages using new proto schema.
  • You can refresh descriptor file only if unknowns fields are faced by the client while parsing. This reduces unneccessary frequent calls made by clients. Currently this feature supported in JAVA and GO clients.

Languages

- + \ No newline at end of file diff --git a/docs/contribute/contribution/index.html b/docs/contribute/contribution/index.html index 2d6911ac..6ec288df 100644 --- a/docs/contribute/contribution/index.html +++ b/docs/contribute/contribution/index.html @@ -10,13 +10,13 @@ Contribution Process | Stencil - +

Contribution Process

The following is a set of guidelines for contributing to Stencil. These are mostly guidelines, not rules. Use your best judgment, and feel free to propose changes to this document in a pull request. Here are some important resources:

How can I contribute?

We use RFCS and GitHub issues to communicate ideas.

  • You can report a bug or suggest a feature enhancement or can just ask questions. Reach out on Github discussions for this purpose.
  • You are also welcome to add new features, improve monitoring,logging and code quality.
  • You can help with documenting new features or improve existing documentation.
  • You can also review and accept other contributions if you are a maintainer.

Please submit a PR to the master branch of the Stencil repository once you are ready to submit your contribution. Code submission to Stencil, including submission from project maintainers, require review and approval from maintainers or code owners. PRs that are submitted by the general public need to pass the build. Once build is passed community members will help to review the pull request.

Becoming a maintainer

We are always interested in adding new maintainers. What we look for is a series of contributions, good taste, and an ongoing interest in the project.

  • maintainers will have write access to the Stencil repositories.
  • There is no strict protocol for becoming a maintainer or PMC member. Candidates for new maintainers are typically people that are active contributors and community members.
  • Candidates for new maintainers can also be suggested by current maintainers or PMC members.
  • If you would like to become a maintainer, you should start contributing to Stencil in any of the ways mentioned. You might also want to talk to other maintainers and ask for their advice and guidance.

Guidelines

Please follow these practices for you change to get merged fast and smoothly:

  • Contributions can only be accepted if they contain appropriate testing (Unit and Integration Tests.)
  • If you are introducing a completely new feature or making any major changes in an existing one, we recommend to start with an RFC and get consensus on the basic design first.
  • Make sure your local build is running with all the tests and golint checks passing.
  • Docs live in the code repo under docs so that changes to that can be done in the same PR as changes to the code.
  • We follow conventional commits for commit messages.
- + \ No newline at end of file diff --git a/docs/formats/avro/index.html b/docs/formats/avro/index.html index fbeb3370..9c5c9db0 100644 --- a/docs/formats/avro/index.html +++ b/docs/formats/avro/index.html @@ -10,13 +10,13 @@ Avro | Stencil - +

Avro

We are in the process of actively improving Stencil documentation. This guide will be updated very soon.

- + \ No newline at end of file diff --git a/docs/formats/json/index.html b/docs/formats/json/index.html index f5857bce..a3459a0f 100644 --- a/docs/formats/json/index.html +++ b/docs/formats/json/index.html @@ -10,13 +10,13 @@ JSON | Stencil - +

JSON

We are in the process of actively improving Stencil documentation. This guide will be updated very soon.

- + \ No newline at end of file diff --git a/docs/formats/protobuf/index.html b/docs/formats/protobuf/index.html index e78fcbfc..f2e6647c 100644 --- a/docs/formats/protobuf/index.html +++ b/docs/formats/protobuf/index.html @@ -10,13 +10,13 @@ Protobuf | Stencil - +

Protobuf

We are in the process of actively improving Stencil documentation. This guide will be updated very soon.

- + \ No newline at end of file diff --git a/docs/glossary/index.html b/docs/glossary/index.html index 7b06e0d9..e6bc3745 100644 --- a/docs/glossary/index.html +++ b/docs/glossary/index.html @@ -10,13 +10,13 @@ Glossary | Stencil - +

Glossary

This section describes the core elements of a schema registry.

Namespace

A named collection of schemas. Each namespace holds a logically related set of schemas, typically managed by a single entity, belonging to a particular application and/or having a shared access control management scope. Since a schema registry is often a resource with a scope greater than a single application and might even span multiple organizations, it is very useful to put a grouping construct around sets of schemas that are related either by ownership or by a shared subject matter context. A namespace has following attributes:

  • ID: Identifies the schema group.
  • Format: Defines the schema format managed by this namespace. e..g Avro, Protobuf, JSON
  • Compatibility Schema compatibility constraint type. e.g. Backward, Forward, Full

Schema

A document describing the structure, names, and types of some structured data payload. Conceptually, a schema is a description of a data structure. Since data structures evolve over time, the schema describing them will also evolve over time. Therefore, a schema often has multiple versions.

Version

A specific version of a schema document. Even though not prescribed in this specification, an implementation might choose to impose compatibility constraints on versions following the initial version of a schema.

Compatibility

A key Schema Registry feature is the ability to version schemas as they evolve. Compatibility policies are created at the namespace or schema level, and define evolution rules for each schema.

After a compatibility policy has been defined for a schema, any subsequent version updates must honor the schema’s original compatibility, to allow for consistent schema evolution.

Compatibility of schemas can be configured with any of the below values:

Backward

Indicates that new version of a schema would be compatible with earlier version of that schema.

Forward

Indicates that an existing schema is compatible with subsequent versions of the schema.

Full

Indicates that a new version of the schema provides both backward and forward compatibilities.

- + \ No newline at end of file diff --git a/docs/guides/clients/index.html b/docs/guides/clients/index.html index 23622a68..88b25421 100644 --- a/docs/guides/clients/index.html +++ b/docs/guides/clients/index.html @@ -10,13 +10,13 @@ Using clients | Stencil - + - + \ No newline at end of file diff --git a/docs/guides/introduction/index.html b/docs/guides/introduction/index.html index 0d3e5aeb..4b81547d 100644 --- a/docs/guides/introduction/index.html +++ b/docs/guides/introduction/index.html @@ -10,13 +10,13 @@ Introduction | Stencil - +

Introduction

This tour introduces you to Stencil schema registry. Along the way you will learn how to manage schemas, enforce rules, serialise and deserialise data using stencil clients.

Prerequisites

This tour requires you to have Stencil CLI tool installed on your local machine. You can run stencil version to verify the installation. Please follow installation guide if you do not have it installed already.

Stencil CLI and clients talks to Stencil server to publish and fetch schema. Please make sure you also have a stencil server running. You can also run server locally with stencil server start command. For more details check deployment guide.

Help

At any time you can run the following commands.

# Check the installed version for stencil cli tool
$ stencil version

# See the help for a command
$ stencil --help

Help command can also be run on any sub command.

$ stencil schema --help

Check the reference for stencil cli commands.

$ stencil reference
- + \ No newline at end of file diff --git a/docs/guides/manage_namespace/index.html b/docs/guides/manage_namespace/index.html index 1981de34..fe5022b6 100644 --- a/docs/guides/manage_namespace/index.html +++ b/docs/guides/manage_namespace/index.html @@ -10,13 +10,13 @@ Manage namespaces | Stencil - + - + \ No newline at end of file diff --git a/docs/guides/manage_schemas/index.html b/docs/guides/manage_schemas/index.html index 09f4fd48..6d930ddc 100644 --- a/docs/guides/manage_schemas/index.html +++ b/docs/guides/manage_schemas/index.html @@ -10,13 +10,13 @@ Manage schemas | Stencil - +

Manage schemas

Create a schema

# create namespace named "quickstart" with backward compatibility enabled
curl -X POST http://localhost:8000/v1beta1/namespaces -H 'Content-Type: application/json' -d '{"id": "quickstart", "format": "FORMAT_PROTOBUF", "compatibility": "COMPATIBILITY_BACKWARD", "description": "This field can be used to store namespace description"}'

# list namespaces
curl http://localhost:8000/v1beta1/namespaces

# upload generated proto descriptor file to server with schema name as `example` under `quickstart` namespace.
curl -X POST http://localhost:8000/v1beta1/namespaces/quickstart/schemas/example --data-binary "@file.desc"

List schema

# get list of schemas available in a namespace
curl -X GET http://localhost:8000/v1beta1/namespaces/quickstart/schemas

View schema

# get list of versions available for particular schema. These versions are auto generated. Version numbers managed by stencil.
curl -X GET http://localhost:8000/v1beta1/namespaces/quickstart/schemas/example/versions

# download specific version of particular schema
curl -X GET http://localhost:8000/v1beta1/namespaces/quickstart/schemas/example/versions/1

# download latest version of particular schema
curl -X GET http://localhost:8000/v1beta1/namespaces/quickstart/schemas/example;

Update schema

# now let's try uploading breaking proto definition. Note that proto field number has changed from 1 to 2.
echo "syntax=\"proto3\";\npackage stencil;\nmessage One {\n int32 field_one = 2;\n}" > one.proto;

# create descriptor file
protoc --descriptor_set_out=./file.desc --include_imports ./**/*.proto;

# now try to upload this descriptor file with same name as before. This call should fail, giving you reason it has failed.
curl -X POST http://localhost:8000/v1/namespaces/quickstart/schemas --data-binary "@file.desc";

# now let's try fixing our proto add a new field without having any breaking changes.
echo "syntax=\"proto3\";\npackage stencil;\nmessage One {\n int32 field_one = 1;\nint32 field_two = 2;\n}" > one.proto;

# create descriptor file
protoc --descriptor_set_out=./file.desc --include_imports ./**/*.proto

# now try to upload this descriptor file with same name as before. This call should succeed
curl -X POST http://localhost:8000/v1/namespaces/quickstart/schemas --data-binary "@file.desc"

List versions


# now try versions api. It should have 2 versions now.
curl -X GET http://localhost:8000/v1beta1/namespaces/quickstart/schemas/example/versions

# upload schema can be called multiple times. Stencil server will retain old version if it's already uploaded. This call won't create new version again. You can verify by using versions API again.
curl -X POST http://localhost:8000/v1/namespaces/quickstart/schemas --data-binary "@file.desc"
- + \ No newline at end of file diff --git a/docs/guides/quickstart/index.html b/docs/guides/quickstart/index.html index 15935988..71ee9ffc 100644 --- a/docs/guides/quickstart/index.html +++ b/docs/guides/quickstart/index.html @@ -10,7 +10,7 @@ Quickstart | Stencil - + @@ -18,7 +18,7 @@

Quickstart

This quick start will explore how to use Stencil command line interface and client libraries inside your application code. As part of this quick start we will start stencil server, create schema and then use stencil clients to serialise and deserialise data using registered schemas.

Prerequisites

  • Docker or a local installation of the Stencil binary.
  • A development environment applicable to one of the languages in this quick start (currently Go, Java, and JavaScript).
  • Postgres database and protoc if your schema format is protobuf.

Step 1: Start server

Run stencil server locally using installed stencil binary. Note: Below command assumes stencil_dev db present in your postgres instance.

$ export DB_CONNECTIONSTRING=postgres://postgres@localhost:5432/stencil_dev?sslmode=disable

# Run database migrations
$ stencil server migrate

# Stencil server
$ stencil server start

# Check if server running
$ curl -X GET http://localhost:8080/ping

Step 2: Create schema

$ mkdir example
$ cd example

# Create a sample proto schema.
$ echo "syntax=\"proto3\";
package stencil;
message One {
int32 field_one = 1;
}" > schema.proto

# Create proto descriptor file
$ protoc --descriptor_set_out=./schema.desc --include_imports ./**/*.proto

Step 3: Upload to server

# --host does not contain the protocol scheme http:// since they internally use GRPC.

# Create namespace named "quickstart" with backward compatibility enabled
$ stencil namespace create quickstart -c COMPATIBILITY_BACKWARD -f FORMAT_PROTOBUF -d "For quickstart guide" --host localhost:8000

# List namespaces
$ stencil namespace list --host localhost:8000

# Upload generated schema proto descriptor file to server with schema name as `example` under `quickstart` namespace.
$ stencil schema create example --namespace=quickstart –-filePath=schema.desc

# Get list of schemas available in a namespace
$ stencil schema list --host localhost:8000

# Get list of versions available for particular schema. These versions are auto generated.
# Version numbers managed by stencil.
$ stencil schema version example -n quickstart --host localhost:8000

# Download specific version of particular schema
$ stencil schema get example --version 1 --host localhost:8000

# Download latest version of particular schema
$ stencil schema get example -n quickstart --host localhost:8000

Step 4: Using client

Let's use this API in our GO client

package main

import (
"log"
stencil "github.com/raystack/stencil/clients/go"
)

func main() {
url := "http://localhost:8000/v1/namespaces/quickstart/descriptors/example/versions/latest"
client, err := stencil.NewClient([]string{url}, stencil.Options{})
if err != nil {
log.Fatal("Unable to create client", err)
return
}
desc, err := client.GetDescriptor("stencil.One")
// ...
}
- + \ No newline at end of file diff --git a/docs/installation/index.html b/docs/installation/index.html index 96395a67..b42d3997 100644 --- a/docs/installation/index.html +++ b/docs/installation/index.html @@ -10,15 +10,15 @@ Installation | Stencil - +

Installation

Stencil installation is simple. You can install Stencil on macOS, Windows, Linux, OpenBSD, FreeBSD, and on any machine. There are several approaches to installing Stencil.

  1. Using a pre-compiled binary
  2. Installing with package manager
  3. Installing with Docker
  4. Installing from source

Binary (Cross-platform)

Download the appropriate version for your platform from releases page. Once downloaded, the binary can be run from anywhere. You don’t need to install it into a global location. This works well for shared hosts and other systems where you don’t have a privileged account. -Ideally, you should install it somewhere in your PATH for easy use. /usr/local/bin is the most probable location.

MacOS

stencil is available via a Homebrew Tap, and as downloadable binary from the releases page:

brew install raystack/tap/stencil

To upgrade to the latest version:

brew upgrade stencil

Linux

stencil is available as downloadable binaries from the releases page. Download the .deb or .rpm from the releases page and install with sudo dpkg -i and sudo rpm -i respectively.

Windows

stencil is available via scoop, and as a downloadable binary from the releases page:

scoop bucket add stencil https://github.com/raystack/scoop-bucket.git

To upgrade to the latest version:

scoop update stencil

Docker

We provide ready to use Docker container images. To pull the latest image:

docker pull raystack/stencil:latest

To pull a specific version:

docker pull raystack/stencil:v0.5.0

Building from source

To compile from source, you will need Go installed and a copy of git in your PATH.

# Clone the repo
$ git clone git@github.com:raystack/stencil.git

# Check all build comamnds available
$ make help

# Build stencil binary file
$ make build

# Check for installed stencil version
$ ./stencil version

Verifying the installation

To verify Stencil is properly installed, run stencil --help on your system. You should see help output. If you are executing it from the command line, make sure it is on your PATH or you may get an error about Stencil not being found.

$ stencil --help
- +Ideally, you should install it somewhere in your PATH for easy use. /usr/local/bin is the most probable location.

MacOS

stencil is available via a Homebrew Tap, and as downloadable binary from the releases page:

brew install raystack/tap/stencil

To upgrade to the latest version:

brew upgrade stencil

Linux

stencil is available as downloadable binaries from the releases page. Download the .deb or .rpm from the releases page and install with sudo dpkg -i and sudo rpm -i respectively.

Windows

stencil is available via scoop, and as a downloadable binary from the releases page:

scoop bucket add stencil https://github.com/raystack/scoop-bucket.git

To upgrade to the latest version:

scoop update stencil

Docker

We provide ready to use Docker container images. To pull the latest image:

docker pull raystack/stencil:latest

To pull a specific version:

docker pull raystack/stencil:v0.5.1

Building from source

To compile from source, you will need Go installed and a copy of git in your PATH.

# Clone the repo
$ git clone git@github.com:raystack/stencil.git

# Check all build comamnds available
$ make help

# Build stencil binary file
$ make build

# Check for installed stencil version
$ ./stencil version

Verifying the installation

To verify Stencil is properly installed, run stencil --help on your system. You should see help output. If you are executing it from the command line, make sure it is on your PATH or you may get an error about Stencil not being found.

$ stencil --help
+ \ No newline at end of file diff --git a/docs/introduction/index.html b/docs/introduction/index.html index 4fd237f1..653f1a1d 100644 --- a/docs/introduction/index.html +++ b/docs/introduction/index.html @@ -10,7 +10,7 @@ Introduction | Stencil - + @@ -18,7 +18,7 @@

Introduction

Welcome to intro guide to Stencil! This guide is the best place to start with Stencil. We cover what Stencil is, what problems it can solve, how it compares to existing schema registry, and how you can get started using it. If you are familiar with the basics of Stencil, the guide provides a more detailed reference of available features.

What is Stencil?

Stencil is a schema registry that provides schema mangement and validation to ensure data compatibility across applications. It enables developers to create, manage and consume schemas dynamically, efficiently, and reliably, and provides a simple way to validate data against those schemas. Stencil support multiple formats including Protobuf, Avro and JSON.

What is schema registry?

Schema registry is the sole source of truth for schema definitions. When producers or developers create a specific data schema for use within the system, the data schema is stored in the registry that is accessible to all consumers and relevant parties. A central schema registry

  • Provides a serving layer for your metadata to build unified documentation for all schemas.
  • Provides an API for storing and retrieving schemas.
  • Stores versioned history of all schemas.
  • Allows evolution of schema as per compatibility settings and prevents breaking changes by validating the compatibility of schemas.
  • Provides clients in multiple languages for serializing and deserializing messages using schemas stored in registry.
  • Publishers and consumers use these clients to serialize, deserialize message when producing them to stream, etc.
  • Provides multiple backends as a storage system to schemas.
  • Help in tackling organisational challenges by data policy enforcement.

Need for schemas

Schema is a strongly typed description of your data/record that clearly defines the structure, type, and meaning of data. Schemas serve as contracts to enforce communication protocol between consumers and producers using messaging systems. It can also serve as a contract between services as well as between teams to establish a common contract of trust between two parties. Lack of schema poses multiple challenges. Data producers can make arbitrary changes to the data which can create issues for downstream services to interpret the data. For example:

  • The field you're looking for doesn't exist anymore because data producers removed it.
  • The type of the field has changed (e.g. what used to be a String is now an Integer)

Schemas in an event-driven architecture should not be an afterthought and should be defined before you start sending the events.

Data formats

When sending data over the network, you need a way to encode data into bytes. There is a wide variety of data serialization formats, including XML, JSON, BSON, YAML, MessagePack, Protocol Buffers, Thrift, and Avro.  Multiple programming languages also provide specific serialization methods but using language-specific serialization makes consuming data very hard in different programming languages.

Choice of format for an application is subject to a variety of factors, including data complexity, necessity for humans to read it, latency, and storage space concerns. A good data format should fulfill the following needs.

  • The data format should be language and platform-neutral which can be used in communication and data storage.
  • The data format should be efficient, provide ease of development, and mature libraries across different programming languages.
  • Serialized data should not take a lot of space, so binary formats are a natural fit.
  • The data format should have very little protocol parsing time.
  • The data format should support the versioning and schema evolution.

Schema evolution

Schema can be changed, producers and consumers can hold different versions of the scheme simultaneously, and it all continues to work. The schema can be changed, producers and consumers can hold different versions of the scheme simultaneously, and it all continues to work. When working with a large production system, this is a highly valuable feature as it allows you to independently update different elements of the system at different times without concerns about compatibility.

- + \ No newline at end of file diff --git a/docs/reference/api/index.html b/docs/reference/api/index.html index 117dce99..7c9e5aae 100644 --- a/docs/reference/api/index.html +++ b/docs/reference/api/index.html @@ -9,14 +9,14 @@ -API | Stencil - +API | Stencil +
-

API

Version: 0.5.0

/v1beta1/namespaces

GET

Summary

List names of namespaces

Responses
CodeDescriptionSchema
200A successful response.v1beta1ListNamespacesResponse
defaultAn unexpected error response.rpcStatus

POST

Summary

Create namespace entry

Parameters
NameLocated inDescriptionRequiredSchema
bodybodyYesv1beta1CreateNamespaceRequest
Responses
CodeDescriptionSchema
200A successful response.v1beta1CreateNamespaceResponse
defaultAn unexpected error response.rpcStatus

/v1beta1/namespaces/{id}

GET

Summary

Get namespace by id

Parameters
NameLocated inDescriptionRequiredSchema
idpathYesstring
Responses
CodeDescriptionSchema
200A successful response.v1beta1GetNamespaceResponse
defaultAn unexpected error response.rpcStatus

DELETE

Summary

Delete namespace by id

Description

Ensure all schemas under this namespace is deleted, otherwise it will throw error

Parameters
NameLocated inDescriptionRequiredSchema
idpathYesstring
Responses
CodeDescriptionSchema
200A successful response.v1beta1DeleteNamespaceResponse
defaultAn unexpected error response.rpcStatus

PUT

Summary

Update namespace entity by id

Parameters
NameLocated inDescriptionRequiredSchema
idpathYesstring
bodybodyYesobject
Responses
CodeDescriptionSchema
200A successful response.v1beta1UpdateNamespaceResponse
defaultAn unexpected error response.rpcStatus

/v1beta1/namespaces/{id}/schemas

GET

Summary

List schemas under the namespace

Parameters
NameLocated inDescriptionRequiredSchema
idpathYesstring
Responses
CodeDescriptionSchema
200A successful response.v1beta1ListSchemasResponse
defaultAn unexpected error response.rpcStatus

/v1beta1/namespaces/{namespaceId}/schemas/{schemaId}

GET

Summary

Get latest schema

Description

Returns latest schema in it's own data type. For protobuf response type would be 'application/octet-stream'. Avro, json schema response type would be 'application/json'

Parameters
NameLocated inDescriptionRequiredSchema
namespaceIdpathYesstring
schemaIdpathYesstring
Responses
CodeDescriptionSchema
200A successful schema response. Based on schema format, response will return different content types. For avro and json schemas response type is application/json. For protobuf response type is application/octet-stream.
defaultAn unexpected error response.rpcStatus

POST

Summary

Create schema under the namespace

Parameters
NameLocated inDescriptionRequiredSchema
namespaceIdpathYesstring
schemaIdpathYesstring
bodybodyRequest payload should be equivalent to curl --data-binary optionYesbinary
Responses
CodeDescriptionSchema
200A successful response.v1beta1CreateSchemaResponse
defaultAn unexpected error response.rpcStatus

DELETE

Summary

Delete specified schema

Parameters
NameLocated inDescriptionRequiredSchema
namespaceIdpathYesstring
schemaIdpathYesstring
Responses
CodeDescriptionSchema
200A successful response.v1beta1DeleteSchemaResponse
defaultAn unexpected error response.rpcStatus

PATCH

Summary

Update only schema metadata

Parameters
NameLocated inDescriptionRequiredSchema
namespaceIdpathYesstring
schemaIdpathYesstring
bodybodyYesobject
Responses
CodeDescriptionSchema
200A successful response.v1beta1UpdateSchemaMetadataResponse
defaultAn unexpected error response.rpcStatus

/v1beta1/namespaces/{namespaceId}/schemas/{schemaId}/check

POST

Summary

Check schema compatibility

Description

Checks comptibility with existing latest schema

Parameters
NameLocated inDescriptionRequiredSchema
namespaceIdpathYesstring
schemaIdpathYesstring
bodybodyYesbinary
X-CompatibilityheaderNostring
Responses
CodeDescriptionSchema
200A successful response.v1beta1CreateSchemaResponse
defaultAn unexpected error response.rpcStatus

/v1beta1/namespaces/{namespaceId}/schemas/{schemaId}/meta

GET

Summary

Create schema under the namespace. Returns version number, unique ID and location

Parameters
NameLocated inDescriptionRequiredSchema
namespaceIdpathYesstring
schemaIdpathYesstring
Responses
CodeDescriptionSchema
200A successful response.v1beta1GetSchemaMetadataResponse
defaultAn unexpected error response.rpcStatus

/v1beta1/namespaces/{namespaceId}/schemas/{schemaId}/versions

GET

Summary

List all version numbers for schema

Parameters
NameLocated inDescriptionRequiredSchema
namespaceIdpathYesstring
schemaIdpathYesstring
Responses
CodeDescriptionSchema
200A successful response.v1beta1ListVersionsResponse
defaultAn unexpected error response.rpcStatus

/v1beta1/namespaces/{namespaceId}/schemas/{schemaId}/versions/{versionId}

DELETE

Summary

Delete specified version of the schema

Parameters
NameLocated inDescriptionRequiredSchema
namespaceIdpathYesstring
schemaIdpathYesstring
versionIdpathYesinteger
Responses
CodeDescriptionSchema
200A successful response.v1beta1DeleteVersionResponse
defaultAn unexpected error response.rpcStatus

/v1beta1/search

GET

Summary

Global Search API

Parameters
NameLocated inDescriptionRequiredSchema
namespaceIdqueryNostring
schemaIdqueryNostring
queryqueryYesstring
historyqueryNoboolean
versionIdqueryNointeger
Responses
CodeDescriptionSchema
200A successful response.v1beta1SearchResponse
defaultAn unexpected error response.rpcStatus

Models

SchemaCompatibility

NameTypeDescriptionRequired
SchemaCompatibilitystring

SchemaFormat

NameTypeDescriptionRequired
SchemaFormatstring

protobufAny

NameTypeDescriptionRequired
typeUrlstringNo
valuebyteNo

rpcStatus

NameTypeDescriptionRequired
codeintegerNo
messagestringNo
details[ protobufAny ]No

v1beta1CheckCompatibilityResponse

NameTypeDescriptionRequired
v1beta1CheckCompatibilityResponseobject

v1beta1CreateNamespaceRequest

NameTypeDescriptionRequired
idstringYes
formatSchemaFormatNo
compatibilitySchemaCompatibilityNo
descriptionstringNo

v1beta1CreateNamespaceResponse

NameTypeDescriptionRequired
namespacev1beta1NamespaceNo

v1beta1CreateSchemaResponse

NameTypeDescriptionRequired
versionintegerNo
idstringNo
locationstringNo

v1beta1DeleteNamespaceResponse

NameTypeDescriptionRequired
messagestringNo

v1beta1DeleteSchemaResponse

NameTypeDescriptionRequired
messagestringNo

v1beta1DeleteVersionResponse

NameTypeDescriptionRequired
messagestringNo

v1beta1GetLatestSchemaResponse

NameTypeDescriptionRequired
databyteNo

v1beta1GetNamespaceResponse

NameTypeDescriptionRequired
namespacev1beta1NamespaceNo

v1beta1GetSchemaMetadataResponse

NameTypeDescriptionRequired
formatSchemaFormatNo
compatibilitySchemaCompatibilityNo
authoritystringNo

v1beta1GetSchemaResponse

NameTypeDescriptionRequired
databyteNo

v1beta1ListNamespacesResponse

NameTypeDescriptionRequired
namespaces[ string ]No

v1beta1ListSchemasResponse

NameTypeDescriptionRequired
schemas[ string ]No

v1beta1ListVersionsResponse

NameTypeDescriptionRequired
versions[ integer ]No

v1beta1Namespace

NameTypeDescriptionRequired
idstringNo
formatSchemaFormatNo
CompatibilitySchemaCompatibilityNo
descriptionstringNo
createdAtdateTimeNo
updatedAtdateTimeNo

v1beta1SearchHits

NameTypeDescriptionRequired
namespaceIdstringNo
schemaIdstringNo
versionIdintegerNo
fields[ string ]No
types[ string ]No
pathstringNo

v1beta1SearchMeta

NameTypeDescriptionRequired
totallongNo

v1beta1SearchResponse

NameTypeDescriptionRequired
hits[ v1beta1SearchHits ]No
metav1beta1SearchMetaNo

v1beta1UpdateNamespaceResponse

NameTypeDescriptionRequired
namespacev1beta1NamespaceNo

v1beta1UpdateSchemaMetadataResponse

NameTypeDescriptionRequired
formatSchemaFormatNo
compatibilitySchemaCompatibilityNo
authoritystringNo
- +

API

Version: 0.5.1

/v1beta1/namespaces

GET

Summary

List names of namespaces

Responses
CodeDescriptionSchema
200A successful response.v1beta1ListNamespacesResponse
defaultAn unexpected error response.rpcStatus

POST

Summary

Create namespace entry

Parameters
NameLocated inDescriptionRequiredSchema
bodybodyYesv1beta1CreateNamespaceRequest
Responses
CodeDescriptionSchema
200A successful response.v1beta1CreateNamespaceResponse
defaultAn unexpected error response.rpcStatus

/v1beta1/namespaces/{id}

GET

Summary

Get namespace by id

Parameters
NameLocated inDescriptionRequiredSchema
idpathYesstring
Responses
CodeDescriptionSchema
200A successful response.v1beta1GetNamespaceResponse
defaultAn unexpected error response.rpcStatus

DELETE

Summary

Delete namespace by id

Description

Ensure all schemas under this namespace is deleted, otherwise it will throw error

Parameters
NameLocated inDescriptionRequiredSchema
idpathYesstring
Responses
CodeDescriptionSchema
200A successful response.v1beta1DeleteNamespaceResponse
defaultAn unexpected error response.rpcStatus

PUT

Summary

Update namespace entity by id

Parameters
NameLocated inDescriptionRequiredSchema
idpathYesstring
bodybodyYesobject
Responses
CodeDescriptionSchema
200A successful response.v1beta1UpdateNamespaceResponse
defaultAn unexpected error response.rpcStatus

/v1beta1/namespaces/{id}/schemas

GET

Summary

List schemas under the namespace

Parameters
NameLocated inDescriptionRequiredSchema
idpathYesstring
Responses
CodeDescriptionSchema
200A successful response.v1beta1ListSchemasResponse
defaultAn unexpected error response.rpcStatus

/v1beta1/namespaces/{namespaceId}/schemas/{schemaId}

GET

Summary

Get latest schema

Description

Returns latest schema in it's own data type. For protobuf response type would be 'application/octet-stream'. Avro, json schema response type would be 'application/json'

Parameters
NameLocated inDescriptionRequiredSchema
namespaceIdpathYesstring
schemaIdpathYesstring
Responses
CodeDescriptionSchema
200A successful schema response. Based on schema format, response will return different content types. For avro and json schemas response type is application/json. For protobuf response type is application/octet-stream.
defaultAn unexpected error response.rpcStatus

POST

Summary

Create schema under the namespace

Parameters
NameLocated inDescriptionRequiredSchema
namespaceIdpathYesstring
schemaIdpathYesstring
bodybodyRequest payload should be equivalent to curl --data-binary optionYesbinary
Responses
CodeDescriptionSchema
200A successful response.v1beta1CreateSchemaResponse
defaultAn unexpected error response.rpcStatus

DELETE

Summary

Delete specified schema

Parameters
NameLocated inDescriptionRequiredSchema
namespaceIdpathYesstring
schemaIdpathYesstring
Responses
CodeDescriptionSchema
200A successful response.v1beta1DeleteSchemaResponse
defaultAn unexpected error response.rpcStatus

PATCH

Summary

Update only schema metadata

Parameters
NameLocated inDescriptionRequiredSchema
namespaceIdpathYesstring
schemaIdpathYesstring
bodybodyYesobject
Responses
CodeDescriptionSchema
200A successful response.v1beta1UpdateSchemaMetadataResponse
defaultAn unexpected error response.rpcStatus

/v1beta1/namespaces/{namespaceId}/schemas/{schemaId}/check

POST

Summary

Check schema compatibility

Description

Checks comptibility with existing latest schema

Parameters
NameLocated inDescriptionRequiredSchema
namespaceIdpathYesstring
schemaIdpathYesstring
bodybodyYesbinary
X-CompatibilityheaderNostring
Responses
CodeDescriptionSchema
200A successful response.v1beta1CreateSchemaResponse
defaultAn unexpected error response.rpcStatus

/v1beta1/namespaces/{namespaceId}/schemas/{schemaId}/meta

GET

Summary

Create schema under the namespace. Returns version number, unique ID and location

Parameters
NameLocated inDescriptionRequiredSchema
namespaceIdpathYesstring
schemaIdpathYesstring
Responses
CodeDescriptionSchema
200A successful response.v1beta1GetSchemaMetadataResponse
defaultAn unexpected error response.rpcStatus

/v1beta1/namespaces/{namespaceId}/schemas/{schemaId}/versions

GET

Summary

List all version numbers for schema

Parameters
NameLocated inDescriptionRequiredSchema
namespaceIdpathYesstring
schemaIdpathYesstring
Responses
CodeDescriptionSchema
200A successful response.v1beta1ListVersionsResponse
defaultAn unexpected error response.rpcStatus

/v1beta1/namespaces/{namespaceId}/schemas/{schemaId}/versions/{versionId}

DELETE

Summary

Delete specified version of the schema

Parameters
NameLocated inDescriptionRequiredSchema
namespaceIdpathYesstring
schemaIdpathYesstring
versionIdpathYesinteger
Responses
CodeDescriptionSchema
200A successful response.v1beta1DeleteVersionResponse
defaultAn unexpected error response.rpcStatus

/v1beta1/search

GET

Summary

Global Search API

Parameters
NameLocated inDescriptionRequiredSchema
namespaceIdqueryNostring
schemaIdqueryNostring
queryqueryYesstring
historyqueryNoboolean
versionIdqueryNointeger
Responses
CodeDescriptionSchema
200A successful response.v1beta1SearchResponse
defaultAn unexpected error response.rpcStatus

Models

SchemaCompatibility

NameTypeDescriptionRequired
SchemaCompatibilitystring

SchemaFormat

NameTypeDescriptionRequired
SchemaFormatstring

protobufAny

NameTypeDescriptionRequired
typeUrlstringNo
valuebyteNo

rpcStatus

NameTypeDescriptionRequired
codeintegerNo
messagestringNo
details[ protobufAny ]No

v1beta1CheckCompatibilityResponse

NameTypeDescriptionRequired
v1beta1CheckCompatibilityResponseobject

v1beta1CreateNamespaceRequest

NameTypeDescriptionRequired
idstringYes
formatSchemaFormatNo
compatibilitySchemaCompatibilityNo
descriptionstringNo

v1beta1CreateNamespaceResponse

NameTypeDescriptionRequired
namespacev1beta1NamespaceNo

v1beta1CreateSchemaResponse

NameTypeDescriptionRequired
versionintegerNo
idstringNo
locationstringNo

v1beta1DeleteNamespaceResponse

NameTypeDescriptionRequired
messagestringNo

v1beta1DeleteSchemaResponse

NameTypeDescriptionRequired
messagestringNo

v1beta1DeleteVersionResponse

NameTypeDescriptionRequired
messagestringNo

v1beta1GetLatestSchemaResponse

NameTypeDescriptionRequired
databyteNo

v1beta1GetNamespaceResponse

NameTypeDescriptionRequired
namespacev1beta1NamespaceNo

v1beta1GetSchemaMetadataResponse

NameTypeDescriptionRequired
formatSchemaFormatNo
compatibilitySchemaCompatibilityNo
authoritystringNo

v1beta1GetSchemaResponse

NameTypeDescriptionRequired
databyteNo

v1beta1ListNamespacesResponse

NameTypeDescriptionRequired
namespaces[ string ]No

v1beta1ListSchemasResponse

NameTypeDescriptionRequired
schemas[ string ]No

v1beta1ListVersionsResponse

NameTypeDescriptionRequired
versions[ integer ]No

v1beta1Namespace

NameTypeDescriptionRequired
idstringNo
formatSchemaFormatNo
CompatibilitySchemaCompatibilityNo
descriptionstringNo
createdAtdateTimeNo
updatedAtdateTimeNo

v1beta1SearchHits

NameTypeDescriptionRequired
namespaceIdstringNo
schemaIdstringNo
versionIdintegerNo
fields[ string ]No
types[ string ]No
pathstringNo

v1beta1SearchMeta

NameTypeDescriptionRequired
totallongNo

v1beta1SearchResponse

NameTypeDescriptionRequired
hits[ v1beta1SearchHits ]No
metav1beta1SearchMetaNo

v1beta1UpdateNamespaceResponse

NameTypeDescriptionRequired
namespacev1beta1NamespaceNo

v1beta1UpdateSchemaMetadataResponse

NameTypeDescriptionRequired
formatSchemaFormatNo
compatibilitySchemaCompatibilityNo
authoritystringNo
+ \ No newline at end of file diff --git a/docs/reference/cli/index.html b/docs/reference/cli/index.html index 7b26010c..fbe7390d 100644 --- a/docs/reference/cli/index.html +++ b/docs/reference/cli/index.html @@ -10,13 +10,13 @@ CLI | Stencil - +

CLI

stencil completion [bash|zsh|fish|powershell]

Generate shell completion scripts

stencil namespace

Manage namespace

stencil namespace create <id> [flags]

Create a namespace

-c, --comp string schema compatibility
-d, --desc string description
-f, --format string schema format
--host string stencil host address eg: localhost:8000

stencil namespace delete <id> [flags]

Delete a namespace

--host string stencil host address eg: localhost:8000

stencil namespace view <id> [flags]

View a namespace

--host string stencil host address eg: localhost:8000

stencil namespace list [flags]

List all namespaces

--host string stencil host address eg: localhost:8000

stencil namespace edit <id> [flags]

Edit a namespace

-c, --comp string schema compatibility
-d, --desc string description
-f, --format string schema format
--host string stencil host address eg: localhost:8000

stencil schema

Manage schema

stencil schema create [flags]

Create a schema

-c, --comp string schema compatibility
-F, --filePath string path to the schema file
-f, --format string schema format
--host string stencil host address eg: localhost:8000
-n, --namespace string parent namespace ID

stencil schema delete [flags]

Delete a schema

    --host string        stencil host address eg: localhost:8000

-n, --namespace string parent namespace ID
-v, --version int32 particular version to be deleted

stencil schema diff [flags]

Diff(s) of two schema versions

    --earlier-version int32   earlier version of the schema
--fullname string only required for FORMAT_PROTO. fullname of proto schema eg: raystack.common.v1.Version
--host string stencil host address eg: localhost:8000
--later-version int32 later version of the schema

-n, --namespace string parent namespace ID

stencil schema get [flags]

View a schema

    --host string        stencil host address eg: localhost:8000

-m, --metadata set this flag to get metadata
-n, --namespace string parent namespace ID
-o, --output string path to the output file
-v, --version int32 version of the schema

stencil schema graph [flags]

Generate file descriptorset dependencies graph

    --host string        stencil host address eg: localhost:8000

-n, --namespace string provide namespace/group or entity name
-o, --output string write to .dot file (default "./proto_vis.dot")
-v, --version int32 provide version number

stencil schema list [flags]

List all schemas

--host string stencil host address eg: localhost:8000

stencil schema print <id> [flags]

Prints snapshot details into .proto files

    --filter-path string   filter protocol buffer files by path prefix, e.g., --filter-path=google/protobuf
--host string stencil host address eg: localhost:8000

-n, --namespace string provide namespace/group or entity name
-o, --output string the directory path to write the descriptor files, default is to print on stdout
-s, --schema string provide proto repo name
-v, --version int32 provide version number

stencil schema update [flags]

Edit a schema

-c, --comp string schema compatibility
--host string stencil host address eg: localhost:8000
-n, --namespace string parent namespace ID

stencil schema version [flags]

Version(s) of a schema

    --host string        stencil host address eg: localhost:8000

-n, --namespace string parent namespace ID

stencil server <command>

Server management

stencil server migrate [flags]

Run database migrations

-c, --config string Config file path (default "./config.yaml")

stencil server start [flags]

Start the server

-c, --config string Config file path (default "./config.yaml")
- + \ No newline at end of file diff --git a/docs/roadmap/index.html b/docs/roadmap/index.html index 6b56f955..ff2e094b 100644 --- a/docs/roadmap/index.html +++ b/docs/roadmap/index.html @@ -10,13 +10,13 @@ Roadmap | Stencil - + - + \ No newline at end of file diff --git a/docs/server/overview/index.html b/docs/server/overview/index.html index f4982f3d..a00ca6bb 100644 --- a/docs/server/overview/index.html +++ b/docs/server/overview/index.html @@ -10,14 +10,14 @@ Overview | Stencil - +

Overview

Stencil is dynamic protobuf schema registry. It provides REST interface for storing and retrieving protobuf file descriptors.

Features

  • stores versioned history of proto descriptor file on specified namespace and name
  • enforce backward compatibility check on upload by default
  • ability to skip some of the backward compatibility checks while upload
  • ability to download fully contained proto descriptor file for specified proto message fullName
  • provides metadata API to retrieve latest version number given a name and namespace

Requirements

  • postgres 13

Installation

Run the following commands to run from docker image

$ docker pull raystack/stencil

Run the following commands to compile from source

$ git clone git@github.com:raystack/stencil.git
$ cd stencil
$ go build -o stencil
$ ./stencil --help

# Create a sample config file.
$ cp config/config.yaml config.yaml

$ ./stencil server start -c config.yaml

Configuring environment Variables

You can also specfify stencil server configurations through following environment variables. Note: ENV vars takes more precendence over config file.

ENVDescription
PORTport number default to 8080
TIMEOUTgraceful time to wait before shutting down the server. Takes time.Duration format. Eg: 30s or 20m
DB_CONNECTIONSTRINGpostgres db connection url. Eg: postgres://postgres@localhost:5432/db_name
NEWRELIC_ENABLEDboolean to enable newrelic
NEWRELIC_APPNAMEappname
NEWRELIC_LICENSELicense key for newrelic

Reference

Quick start API usage examples

The following assumes you have Stencil server up and running at port 8080 and protoc is installed.

$ mkdir example
$ cd example
# create example proto file. You can add as many proto files as you want.
$ echo "syntax=\"proto3\";\npackage stencil;\nmessage One {\n int32 field_one = 1;\n}" > 1.proto

# create descriptor file
$ protoc --descriptor_set_out=./file.desc --include_imports ./1.proto

# create namespace named "quickstart" with backward compatibility enabled
curl -X POST http://localhost:8000/v1beta1/namespaces -H 'Content-Type: application/json' -d '{"id": "quickstart", "format": "FORMAT_PROTOBUF", "compatibility": "COMPATIBILITY_BACKWARD", "description": "This field can be used to store namespace description"}'

# list namespaces
curl http://localhost:8000/v1beta1/namespaces

# upload generated proto descriptor file to server with schema name as `example` under `quickstart` namespace.
curl -X POST http://localhost:8000/v1beta1/namespaces/quickstart/schemas/example --data-binary "@file.desc"

# get list of schemas available in a namespace
curl -X GET http://localhost:8000/v1beta1/namespaces/quickstart/schemas

# get list of versions available for particular schema. These versions are auto generated. Version numbers managed by stencil.
curl -X GET http://localhost:8000/v1beta1/namespaces/quickstart/schemas/example/versions

# download specific version of particular schema
curl -X GET http://localhost:8000/v1beta1/namespaces/quickstart/schemas/example/versions/1

# download latest version of particular schema
curl -X GET http://localhost:8000/v1beta1/namespaces/quickstart/schemas/example;

# now let's try uploading breaking proto definition. Note that proto field number has changed from 1 to 2.
echo "syntax=\"proto3\";\npackage stencil;\nmessage One {\n int32 field_one = 2;\n}" > one.proto;

# create descriptor file
protoc --descriptor_set_out=./file.desc --include_imports ./**/*.proto;

# now try to upload this descriptor file with same name as before. This call should fail, giving you reason it has failed.
curl -X POST http://localhost:8000/v1/namespaces/quickstart/schemas --data-binary "@file.desc";

# now let's try fixing our proto add a new field without having any breaking changes.
echo "syntax=\"proto3\";\npackage stencil;\nmessage One {\n int32 field_one = 1;\nint32 field_two = 2;\n}" > one.proto;

# create descriptor file
protoc --descriptor_set_out=./file.desc --include_imports ./**/*.proto

# now try to upload this descriptor file with same name as before. This call should succeed
curl -X POST http://localhost:8000/v1/namespaces/quickstart/schemas --data-binary "@file.desc"

# now try versions api. It should have 2 versions now.
curl -X GET http://localhost:8000/v1beta1/namespaces/quickstart/schemas/example/versions

# upload schema can be called multiple times. Stencil server will retain old version if it's already uploaded. This call won't create new version again. You can verify by using versions API again.
curl -X POST http://localhost:8000/v1/namespaces/quickstart/schemas --data-binary "@file.desc"
- + \ No newline at end of file diff --git a/docs/server/rules/index.html b/docs/server/rules/index.html index 19e72649..9690a350 100644 --- a/docs/server/rules/index.html +++ b/docs/server/rules/index.html @@ -10,13 +10,13 @@ Compatability rules | Stencil - +

Compatability rules

Stencil server provides following compatibility rules.

  • BACKWARD_COMPATIBILITY
  • FORWARD_COMPATIBILITY
  • FULL_COMPATIBILITY

Stencil currently supports protobuf, avro and json schema formats. Compatibility rules for each schema format has been built separately considering each schema format's features.

Feature support matrix

Compatability ruleProtobufAvroJSON
BACKWARD_COMPATIBILITYYesYesNo
FORWARD_COMPATIBILITYYesYesNo
FULL_COMPATIBILITYYesYesNo

Protobuf compatibility rules

Protobuf compatibility rules composed of compatibility checks.

Rules

Compatibility nameList of checks
BACKWARD_COMPATIBILITYSYNTAX_CHANGE, MESSAGE_DELETE, NON_INCLUSIVE_RESERVED_RANGE, NON_INCLUSIVE_RESERVED_NAMES, FIELD_DELETE, FIELD_JSON_NAME_CHANGE, FIELD_LABEL_CHANGE, FIELD_KIND_CHANGE, FIELD_TYPE_CHANGE, ENUM_DELETE, ENUM_VALUE_DELETE, ENUM_VALUE_NUMBER_CHANGE
FORWARD_COMPATIBILITYSYNTAX_CHANGE, MESSAGE_DELETE, NON_INCLUSIVE_RESERVED_RANGE, NON_INCLUSIVE_RESERVED_NAMES, FIELD_JSON_NAME_CHANGE, FIELD_LABEL_CHANGE, FIELD_KIND_CHANGE, FIELD_TYPE_CHANGE, FIELD_DELETE_WITHOUT_RESERVED_NUMBER, FIELD_DELETE_WITHOUT_RESERVED_NAME, ENUM_DELETE, ENUM_VALUE_NUMBER_CHANGE, ENUM_VALUE_DELETE_WITHOUT_RESERVEDNUMBER, ENUM_VALUE_DELETE_WITHOUT_RESERVEDNAME
FULL_COMPATIBILITYSYNTAX_CHANGE, MESSAGE_DELETE, NON_INCLUSIVE_RESERVED_RANGE, NON_INCLUSIVE_RESERVED_NAMES, FIELD_DELETE, FIELD_JSON_NAME_CHANGE, FIELD_LABEL_CHANGE, FIELD_KIND_CHANGE, FIELD_TYPE_CHANGE, ENUM_DELETE, ENUM_VALUE_DELETE, ENUM_VALUE_NUMBER_CHANGE

List of Checks

CheckDescription
SYNTAX_CHANGEchecks if proto file syntax does not switch between proto2 and proto3, including going to/from unset (which assumes proto2) to set to proto3. Changing the syntax results in differences in generated code for many languages.
MESSAGE_DELETEchecks that messages are deleted from a given file. Deleting a message will delete the corresponding generated type, which could be referenced in source code. Instead of deleting these types, deprecate them using deprecated option.
NON_INCLUSIVE_RESERVED_NAMESChecks if current reserved names contains all previous reserved names.
NON_INCLUSIVE_RESERVED_RANGEChecks if current reserve range inclusive of previous reserved range. This check ensures previous reserved tag numbers haven't been deleted
FIELD_DELETEchecks that no message field is deleted. Deleting message field will result in the field being deleted from the generated source code, which could be referenced. Instead of deleting these, deprecate them using deprecated option.
FIELD_JSON_NAME_CHANGEChecks if the json_name for field does not change, which would break JSON compatibility.
FIELD_LABEL_CHANGEchecks that no field changes it's label, i.e. optional, required, repeated. Changing to/from optional/required and repeated will be a generated source code and JSON breaking change. Changing to/from optional and repeated is actually not a wire-breaking change, however changing to/from optional and required is. Given that it's unlikely to be advisable in any situation to change your label, and that there is only one exception, we find it best to just outlaw this entirely.
FIELD_KIND_CHANGEchecks that a field has the same type. Changing the type of a field can affect the type in the generated source code, wire compatibility, and JSON compatibility.
FIELD_TYPE_CHANGEChecks if message/enum field it's message/enum type has changed from previous version. This rule only applies to message kind and enum kind.
FIELD_DELETE_WITHOUT_RESERVED_NUMBERChecks if field is deleted, it's tag number should be added to reserved numbers. This will ensure deleted field tag number won't be used in future.
FIELD_DELETE_WITHOUT_RESERVED_NAMEChecks if field is deleted, it's tag name should be added to reserved names. This will help to keep the JSON compatibility.
ENUM_DELETEChecks that no enum is deleted from current version. Deleting an enum will delete the corresponding generated type, which could be referenced in source code. Instead of deleting these types, deprecate them using deprecated option.
ENUM_VALUE_DELETEChecks that no enum value is deleted. Deleting an enum value will result in the corresponding value being deleted from the generated source code, which could be referenced. Instead of deleting these, deprecate them.
ENUM_VALUE_DELETE_WITHOUT_RESERVEDNUMBERChecks if enum value deleted, it's enum number should be added to reserved numbers.
ENUM_VALUE_DELETE_WITHOUT_RESERVEDNAMEChecks if enum value deleted, it's enum name should be added to reserved names. This will help to keep the JSON compatibility
ENUM_VALUE_NUMBER_CHANGECheck if enum number has changed between current, previous versions. For example You cannot change FOO_ONE = 1 to FOO_ONE = 2. Doing so will result in potential JSON incompatibilites and broken source code.
- + \ No newline at end of file diff --git a/docs/usecases/index.html b/docs/usecases/index.html index 61c459d0..0601cda3 100644 --- a/docs/usecases/index.html +++ b/docs/usecases/index.html @@ -10,13 +10,13 @@ Usecases | Stencil - +

Usecases

This page describes popular Stencil use cases and provides related resources that you can use to create Stencil workflows.

Event-driven architecture

Event-driven architecture is a software paradigm that promotes using events as a means of communication between decoupled services. Events are the records of a change in state, e.g. a customer booking an order, driver, a driver confirming the booking, etc. Events are immutable and are usually ordered in the sequence of their creation.

Event-driven architecture usually has three key components: producers, message brokers, and consumers. Consumer and producer services are loosely where event producers don't know which events consumers are listening to. This decoupling allows producers and consumers to evolve, scale, and deploy independently.

But this also opens a challenge for managing data schema across consumers and producers.

- + \ No newline at end of file diff --git a/help/index.html b/help/index.html index f2dcad14..9b6ed51e 100644 --- a/help/index.html +++ b/help/index.html @@ -10,13 +10,13 @@ Help | Stencil - +

Need help?

Need a bit of help? We're here for you. Check out our current issues, GitHub discussions, or get support through Slack.

Slack

The Stencil team has an open source slack workspace to discuss development and support. Most of the Stencil discussions happen in #stencil channel.
Join us on Slack

GitHub Issues

Have a general issue or bug that you've found? We'd love to hear about it in our GitHub issues. This can be feature requests too!
Go to issues

GitHub Discussions

For help and questions about best practices, join our GitHub discussions. Browse and ask questions.
Go to discussions
- + \ No newline at end of file diff --git a/index.html b/index.html index a5968efa..a96d3403 100644 --- a/index.html +++ b/index.html @@ -10,13 +10,13 @@ Schema registry engineered for scale | Stencil - +

Built for scale

Stencil is a schema registry that provides schema mangement and validation to ensure data compatibility across applications. It enables developers to create, manage and consume schemas dynamically, efficiently, and reliably, and provides a simple way to validate data against those schemas.

Version history

Stencil stores versioned history of proto descriptor file on specified namespace and name.

Backward compatibility

Enforce backward compatibility check on upload by default.

Flexbility

Ability to skip some of the backward compatibility checks while upload.

Descriptor fetch

Ability to download proto descriptor files.

Metadata

Provides metadata API to retrieve latest version number given a name and namespace.

Clients

Stencil provides clients in GO, JAVA, JS languages to interact with Stencil server and deserialize messages using dynamic schema.

Trusted by

Meteor was originally created for the Gojek data processing platform, and it has been used, adapted and improved by other teams internally and externally.

- + \ No newline at end of file