<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Rick Lee on Medium]]></title>
        <description><![CDATA[Stories by Rick Lee on Medium]]></description>
        <link>https://medium.com/@ricklee_10931?source=rss-88c7c2b846------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/0*1HB2Qs1N5W9Q1gT2.</url>
            <title>Stories by Rick Lee on Medium</title>
            <link>https://medium.com/@ricklee_10931?source=rss-88c7c2b846------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Fri, 29 May 2026 17:54:45 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@ricklee_10931/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[React Multi-lingual with react-i18next]]></title>
            <link>https://medium.com/free-code-camp/react-multi-lingual-with-react-i18next-57879f986168?source=rss-88c7c2b846------2</link>
            <guid isPermaLink="false">https://medium.com/p/57879f986168</guid>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[react]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[tech]]></category>
            <category><![CDATA[multilingualism]]></category>
            <dc:creator><![CDATA[Rick Lee]]></dc:creator>
            <pubDate>Tue, 26 Feb 2019 11:24:34 GMT</pubDate>
            <atom:updated>2019-02-26T11:24:34.681Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*m8n4yc-F8Ln4EcnbL3H-CQ.jpeg" /><figcaption>Photo by <a href="https://unsplash.com/photos/YeO44yVTl20?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Vladislav Klapin</a> on <a href="https://unsplash.com/search/photos/international?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><p>When we build an international web site, multi-lingual support is always one of the essential feature. Fortunately, if we use React, there are quite some awesome libraries that come in handy and <a href="https://github.com/i18next/react-i18next">react-i18next</a> is one of the most popular open source libraries and here is simple example to get it started.</p><p>The very first thing is always to create a react app using create-react-app and install those necessary npm packages.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/35b662c96f365a79551c12874ba33b89/href">https://medium.com/media/35b662c96f365a79551c12874ba33b89/href</a></iframe><p>And here we put those translations to static json files and you can put it in Rest endpoint if you want.</p><p>Create assets directory in public folder.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/64852429c436fcdc8c60790aaf2712a1/href">https://medium.com/media/64852429c436fcdc8c60790aaf2712a1/href</a></iframe><p>And then create 2 simple translation files, one for English and one for traditional Chinese and put them in public/assets/i18n/translations folder.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/e251f6838d3eaf1f746f170d3b8df51b/href">https://medium.com/media/e251f6838d3eaf1f746f170d3b8df51b/href</a></iframe><p>The next step is to create the i18next configuration/initiation script. Let’s create a file, i18n.js, under the src directory:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/4b8eecd2d475f699066a9eba20af1b20/href">https://medium.com/media/4b8eecd2d475f699066a9eba20af1b20/href</a></iframe><p>Now let’s create 2 dummy components, one to show the “Hello” string and the other shows “Thank You”. The react-i18next library provides several ways to access translations, e.g., context API, hooks, HOC, etc. In the following sample codes, the Hello.js uses hooks and ThankYou.js uses HOC.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/c5917a7764e3717776b4e27a715b7f14/href">https://medium.com/media/c5917a7764e3717776b4e27a715b7f14/href</a></iframe><p>Now let’s create a simple language selector that contains a 2 radio buttons for us to choose between English and Traditional Chinese. For the following codes, you can see we can simply pass the locale name to the <strong>i18n.changeLanguage</strong> function to switch between languages.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/c4ec0acedc45bdf3d3a7a2d45511066d/href">https://medium.com/media/c4ec0acedc45bdf3d3a7a2d45511066d/href</a></iframe><p>Finally, let’s modify the App.js to show all the components we have created so far. You can see we use Suspense here, as the react-i18next loads locale resources file asynchronously and we have to wait until the loading is completed before we can use it.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/30bbab3dbede73fe7db2b6c251a1391d/href">https://medium.com/media/30bbab3dbede73fe7db2b6c251a1391d/href</a></iframe><p>The result!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/800/1*VlLMvaEoc_xkCvo3G--wfw.gif" /></figure><p>Github for source codes : <a href="https://github.com/rickcodetalk/test-react-i18next">https://github.com/rickcodetalk/test-react-i18next</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=57879f986168" width="1" height="1" alt=""><hr><p><a href="https://medium.com/free-code-camp/react-multi-lingual-with-react-i18next-57879f986168">React Multi-lingual with react-i18next</a> was originally published in <a href="https://medium.com/free-code-camp">We’ve moved to freeCodeCamp.org/news</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How to set up Vertx in Spring]]></title>
            <link>https://medium.com/free-code-camp/vertx-in-spring-39c2dd7bc2a9?source=rss-88c7c2b846------2</link>
            <guid isPermaLink="false">https://medium.com/p/39c2dd7bc2a9</guid>
            <category><![CDATA[java]]></category>
            <category><![CDATA[tech]]></category>
            <category><![CDATA[vertx]]></category>
            <category><![CDATA[mysql]]></category>
            <category><![CDATA[spring-boot]]></category>
            <dc:creator><![CDATA[Rick Lee]]></dc:creator>
            <pubDate>Mon, 11 Feb 2019 01:43:36 GMT</pubDate>
            <atom:updated>2019-02-28T22:04:05.849Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*zOLXCXhrX_NgyWJf3KGmrQ.jpeg" /></figure><p><a href="https://spring.io/">Spring</a> is probably the most popular framework in the Java space. We all love its dependency injection and all that autowired/configuration magic. It makes unit testing a piece of cake.</p><p>On the other hand, <a href="https://vertx.io/">Vertx.io</a>, which is a newer toolkit/framework, is gaining traction in recent years. It is light-weight and supports fully asynchronous programming via event loop like Node.js and eventbus messaging like Akka. Also, the community has made quite a lot of asynchronous tools/db clients like <a href="https://vertx.io/docs/vertx-mysql-postgresql-client/java/">Async MySQL / PostgreSQL Client</a>, which make it another trendy choice besides Spring.</p><p>It seems that it’s tough to choose between Vertx and Spring for new projects, but the good news is they are indeed not mutually exclusive! The following is a simple example to illustrate the setup.</p><p>This example project is about deploying a Vertical in a Springboot application. The Vertical provides a function for querying MySQL using an Async MySQL client. The function can be called directly or via vertx.eventbus.</p><p>First of all, create a simple maven Springboot application. You can create it through <a href="https://start.spring.io/">Spring Initializer</a>. Then add the following to the pom.xml:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/92f083e4733634ab927c1dfb159aedd4/href">https://medium.com/media/92f083e4733634ab927c1dfb159aedd4/href</a></iframe><p>As we’re going to query mysql using <a href="https://vertx.io/docs/vertx-mysql-postgresql-client/java/">Async MySQL / PostgreSQL Client</a>, a very primitive MysqlClient.java is created and the MySQL configuration is put on the application.yaml.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/2c56955772940dcb4d4a5dd50022fc47/href">https://medium.com/media/2c56955772940dcb4d4a5dd50022fc47/href</a></iframe><p>Create a dummy user table with 2 fields and insert some data:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/99f5d0cbb1e481f76f5d3274f0010106/href">https://medium.com/media/99f5d0cbb1e481f76f5d3274f0010106/href</a></iframe><p>Optionally, create a repository class for accessing the user table:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/4f4a2334ad39bb822da92dbfc9438b08/href">https://medium.com/media/4f4a2334ad39bb822da92dbfc9438b08/href</a></iframe><p>Now we can create the vertical, which has a single method for handling MySQL queries.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/78b0af7517740088b4c0dc93b060005c/href">https://medium.com/media/78b0af7517740088b4c0dc93b060005c/href</a></iframe><p>Finally, create the Spring application and add a deployVerticle method with the @PostConstruct annotation.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/0e64e5c9b07b1271d234c15d469ed663/href">https://medium.com/media/0e64e5c9b07b1271d234c15d469ed663/href</a></iframe><p>If you run the Spring application, you will see the following System printout of “dbVerticle deployed” and it means the Verticle is running on the Spring application.</p><pre>2019-02-11 08:56:27.110  INFO 29444 --- [ntloop-thread-0] i.v.ext.asyncsql.impl.MYSQLClientImpl    : Creating configuration for localhost:3306<br>2019-02-11 08:56:27.442  INFO 29444 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService &#39;applicationTaskExecutor&#39;<br><strong>dbVerticle deployed</strong><br>2019-02-11 08:56:27.848  INFO 29444 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path &#39;&#39;<br>2019-02-11 08:56:27.853  INFO 29444 --- [           main] n.r.s.SpringVertxExampleApplication      : Started SpringVertxExampleApplication in 5.393 seconds (JVM running for 6.671)</pre><p>To test it, we can simply add a db query request right after the Verticle was deployed.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/a15b44dda36497f9e5076142d7d13a76/href">https://medium.com/media/a15b44dda36497f9e5076142d7d13a76/href</a></iframe><p>The console prints out the following:</p><pre>dbVerticle deployed<br>success<br>[{&quot;id&quot;:10466,&quot;username&quot;:&quot;ricklee&quot;}]<br>[{&quot;id&quot;:10468,&quot;username&quot;:&quot;maryjohnson&quot;}]</pre><p>This example illustrated how you can enjoy the facilities from both the Spring and Vertx world with a simple setup.</p><p>Source code here: <a href="https://github.com/rickcodetalk/spring-vertx-example">https://github.com/rickcodetalk/spring-vertx-example</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=39c2dd7bc2a9" width="1" height="1" alt=""><hr><p><a href="https://medium.com/free-code-camp/vertx-in-spring-39c2dd7bc2a9">How to set up Vertx in Spring</a> was originally published in <a href="https://medium.com/free-code-camp">We’ve moved to freeCodeCamp.org/news</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Envoy External Authorization — A simple example]]></title>
            <link>https://medium.com/free-code-camp/envoy-external-authorization-a-simple-example-d50ef2ede631?source=rss-88c7c2b846------2</link>
            <guid isPermaLink="false">https://medium.com/p/d50ef2ede631</guid>
            <category><![CDATA[docker]]></category>
            <category><![CDATA[envoy]]></category>
            <category><![CDATA[envoy-proxy]]></category>
            <category><![CDATA[microservices]]></category>
            <category><![CDATA[authorization]]></category>
            <dc:creator><![CDATA[Rick Lee]]></dc:creator>
            <pubDate>Tue, 29 Jan 2019 11:31:38 GMT</pubDate>
            <atom:updated>2019-02-15T01:50:22.044Z</atom:updated>
            <content:encoded><![CDATA[<h3>Envoy External Authorization — A simple example</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*XouYRWAoPrK0liDyOQWZBA.jpeg" /><figcaption>Photo by <a href="https://unsplash.com/photos/N2HtDFA-AgM?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Ishan @seefromthesky</a> on <a href="https://unsplash.com/search/photos/network?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/643/1*7TG97FOYpfE0LLkvfff0NQ.jpeg" /></figure><p>Newer version of Envoy (after v1.17.0?) supports a feature, <strong>External Authorization</strong> (part of the v2 API), which you can configure the network or http filter to call external service (via http or gRPC) for authentication/authorization purpose. This is a very simple example to illustrate the setup.</p><p>This example is based on the front-proxy example in official Envoy github</p><pre><a href="https://github.com/envoyproxy/envoy/tree/master/examples/front-proxy">https://github.com/envoyproxy/envoy/tree/master/examples/front-proxy</a></pre><p>After cloning the example from github, go to the examples/front-proxy directory and run</p><pre>~/Documents/envoy-ext-authz 🐰$ docker-compose up -d<br>Starting envoy-ext-authz_service2_1    ... done<br>Starting envoy-ext-authz_front-envoy_1 ... done<br>Starting envoy-ext-authz_service1_1    ... done<br></pre><p>The front-envoy and 2 services with side-car envoy dockers are running. Try to access the <a href="http://localhost:8000/service/1">http://localhost:8000/service/1</a> endpoint using Postman.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/655/1*w4ZSGy0Op11JuMKtXjwX5Q.png" /></figure><p>Now what about if we want to authenticate the request before it’s passed to upstream services?</p><p>First of all, let’s create a dummy authentication service using express that will extract the basic auth header and validate the username and password in hardcoded manner.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/e4554739a57f501e10465591775b23b6/href">https://medium.com/media/e4554739a57f501e10465591775b23b6/href</a></iframe><p>Dockerize it</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/179184777b9759836d31cbb1ec5235f9/href">https://medium.com/media/179184777b9759836d31cbb1ec5235f9/href</a></iframe><p>Add the following to the docker-compose.yml</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/7599849b6956af1ca42b9ea1429fe6f9/href">https://medium.com/media/7599849b6956af1ca42b9ea1429fe6f9/href</a></iframe><p>Run docker-compose build</p><pre>~/Documents/envoy-ext-authz 🐰$ docker-compose up --build</pre><p>Now there should be 4 docker containers running:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/2c6a645a9818637e58262969bbdd1885/href">https://medium.com/media/2c6a645a9818637e58262969bbdd1885/href</a></iframe><p>The final step is to modify the front-envoy.yaml. In the filter section, add the envoy.ext-authz filter and under the clusters section, add the auth service cluster.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/2b530b2679f40a35c104fce0b218be02/href">https://medium.com/media/2b530b2679f40a35c104fce0b218be02/href</a></iframe><p>All set! Let’s run the request again</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/659/1*MtrVrGwDqawH5gHWTsejqw.png" /></figure><p>It got a 403 Forbidden without setting the basic auth header.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/661/1*S6vHVO1Tqcz3MMAlwO9uAg.png" /></figure><p>The request is directed to service 1 successful when the username &amp; password is correct.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/661/1*HN5IXeCrrzcj-b6hVh1YwA.png" /></figure><p>Got 401 when the password didn’t match.</p><h3><strong>Restriction</strong></h3><p>It’s pretty straight forward, but one of restriction I encountered is the request body cannot be passed to the external auth service, so if you do something like verifying digital signature against the request body, it won’t work.</p><h3>Source Code</h3><p><a href="https://github.com/rickcodetalk/envoy-ext-authz">https://github.com/rickcodetalk/envoy-ext-authz</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=d50ef2ede631" width="1" height="1" alt=""><hr><p><a href="https://medium.com/free-code-camp/envoy-external-authorization-a-simple-example-d50ef2ede631">Envoy External Authorization — A simple example</a> was originally published in <a href="https://medium.com/free-code-camp">We’ve moved to freeCodeCamp.org/news</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Redis streams — yet another unified log?]]></title>
            <link>https://medium.com/@ricklee_10931/redis-streams-yet-another-unified-log-d18493822130?source=rss-88c7c2b846------2</link>
            <guid isPermaLink="false">https://medium.com/p/d18493822130</guid>
            <category><![CDATA[kafka]]></category>
            <category><![CDATA[redis]]></category>
            <category><![CDATA[microservices]]></category>
            <dc:creator><![CDATA[Rick Lee]]></dc:creator>
            <pubDate>Fri, 25 Jan 2019 07:44:06 GMT</pubDate>
            <atom:updated>2019-01-25T07:44:06.424Z</atom:updated>
            <content:encoded><![CDATA[<h3>Redis streams — yet another unified log?</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*i1d88Q8NNrRv6kjf7Ssw4g.png" /></figure><p>Redis 5 was released several months ago and the most exciting new feature is probably the <strong><em>Redis streams</em></strong>. It was expected to be included in Redis 4, but got delay and delay…This new feature extends the Redis capability to make it cover part of the Kafka and RabbitMQ (RabbitMQ has more fancy features, but not everyone cares)’s core functionality, which is the unified log. The following demonstrates the feature via simple command lines:</p><h4>To create or add item to the stream:</h4><pre>/* <br>   symbols is the log name, * means default id which is <br>   current timestamp + running sequence and follow by<br>   1 or multiple field/value pair(s)<br>*/ <br>127.0.0.1:6379&gt; xadd stocks * symbol AAPL last 164.23<br>&quot;1545111644949-0&quot;<br>127.0.0.1:6379&gt; xadd stocks * symbol TSLA last 300.13 <br>&quot;1545111689782-0&quot;<br>127.0.0.1:6379&gt; xadd stocks * symbol FB last 144.22 <br>&quot;1545111721902-0&quot;</pre><h4>To get the length of the stream:</h4><pre>127.0.0.1:6379&gt; xlen stocks <br>(integer) 3</pre><h4>To query the stream by range:</h4><pre>/*  <br>  &quot;-&quot; means the first item  <br>  &quot;+&quot; means the last item  <br>  &quot;xrange stocks - +&quot; means get all items <br>*/ <br>127.0.0.1:6379&gt; xrange stocks - + <br>1) 1) &quot;1545111644949-0&quot;    <br>   2) 1) &quot;symbol&quot;       <br>      2) &quot;AAPL&quot;       <br>      3) &quot;last&quot;       <br>      4) &quot;164.23&quot; <br>2) 1) &quot;1545111689782-0&quot;    <br>   2) 1) &quot;symbol&quot;       <br>      2) &quot;TSLA&quot;       <br>      3) &quot;last&quot;       <br>      4) &quot;300.13&quot; <br>3) 1) &quot;1545111721902-0&quot;    <br>   2) 1) &quot;symbol&quot;       <br>      2) &quot;FB&quot;       <br>      3) &quot;last&quot;       <br>      4) &quot;144.22&quot;</pre><h4>To query the stream from a specific timestamp to the last item:</h4><pre>/*   <br>  Doesn&#39;t need to include the running sequence of the id <br>*/ <br>127.0.0.1:6379&gt; xrange stocks 1545111689782 + <br>1) 1) &quot;1545111689782-0&quot;    <br>   2) 1) &quot;symbol&quot;       <br>      2) &quot;TSLA&quot;       <br>      3) &quot;last&quot;       <br>      4) &quot;300.13&quot; <br>2) 1) &quot;1545111721902-0&quot;    <br>   2) 1) &quot;symbol&quot;       <br>      2) &quot;FB&quot;       <br>      3) &quot;last&quot;       <br>      4) &quot;144.22&quot;</pre><h4>To listen new item:</h4><pre>/* listening client */ <br>127.0.0.1:6379&gt; xread block 0 streams stocks 1545111721902</pre><pre>/* On other client, add a new entry */ <br>127.0.0.1:6379&gt; xadd stocks * symbol MSFT last 103.20 <br>&quot;1545112652244-0&quot;</pre><pre>/* On the listening client */ <br>127.0.0.1:6379&gt; xread block 0 streams stocks 1545111721902 <br>1) 1) &quot;stocks&quot;    <br>   2) 1) 1) &quot;1545112652244-0&quot;          <br>         2) 1) &quot;symbol&quot;             <br>            2) &quot;MSFT&quot;             <br>            3) &quot;last&quot;             <br>            4) &quot;103.20&quot;</pre><h4>To create consumer group:</h4><pre>/* tradingservice is the consumer group name */ <br>127.0.0.1:6379&gt; xgroup create stocks tradingservice $ <br>OK</pre><h4>Consumer group to listen to new item:</h4><pre>/* Client 1 - instance1 is the client name */ <br>127.0.0.1:6379&gt; xreadgroup block 0 group tradingservice instance1 streams stocks &gt;</pre><pre>/* Client 2 */ <br>127.0.0.1:6379&gt; xreadgroup block 0 group tradingservice instance2 streams stocks &gt;</pre><pre>/* Other client to add new item to the stream */ <br>127.0.0.1:6379&gt; xadd stocks * symbol NFLX last 310.87 <br>&quot;1545113281486-0&quot;  </pre><pre>/* Client 1 got the data */ <br>127.0.0.1:6379&gt; xreadgroup block 0 group tradingservice instance1 streams stocks &gt; <br>1) 1) &quot;stocks&quot;    <br>   2) 1) 1) &quot;1545113281486-0&quot;          <br>         2) 1) &quot;symbol&quot;             <br>            2) &quot;NFLX&quot;             <br>            3) &quot;last&quot;             <br>            4) &quot;310.87&quot;              </pre><pre>/* Other client to add new item to the stream */ <br>127.0.0.1:6379&gt; xadd stocks * symbol GOOGL last 1032.34 <br>&quot;1545113291736-0&quot;  </pre><pre>/* Client 2 got the data */ <br>127.0.0.1:6379&gt; xreadgroup block 0 group tradingservice instance2 streams stocks &gt; <br>1) 1) &quot;stocks&quot;    <br>   2) 1) 1) &quot;1545113291736-0&quot;          <br>         2) 1) &quot;symbol&quot;             <br>            2) &quot;GOOGL&quot;             <br>            3) &quot;last&quot;             <br>            4) &quot;1032.34&quot;</pre><p>That’s only a simple example. The Redis streams does have other useful command like client acknowledgement and recovery of pending items, etc.</p><h4>The consideration of choosing Redis streams as the pub/sub unified log technology:</h4><p>General speaking it’s very situational. If you’re building an application that’s more monolithic and is always hosted in a single premises, you can have more choices, you can use Redis, Kafka, ActiveMQ, RabitMQ or even mix of them (not recommended tho). However, if you need to build an extremely scalable/portable application in which you can deploy it to multiple locations easily, e.g., per country, per region, or even per customer or even able to install in customers’ premises or even able to install in one single small device/computer, you must be cautious and choose only simple (as simple as possible) technology stack. Then Redis may be a good choice, as</p><ul><li>It’s very possibly it’s in your original tech stack already, so no additional third-party component to be maintained.</li><li>It’s offered by AWS as ElasticCache service and that enables auto-provisioning and also make those configuration, maintenance and scale up/down in near zero effort.</li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=d18493822130" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Kotlin 1.3 Coroutine]]></title>
            <link>https://medium.com/@ricklee_10931/kotlin-1-3-coroutine-8eb76af2ce5b?source=rss-88c7c2b846------2</link>
            <guid isPermaLink="false">https://medium.com/p/8eb76af2ce5b</guid>
            <category><![CDATA[coroutine]]></category>
            <category><![CDATA[concurrent-programming]]></category>
            <category><![CDATA[kotlin]]></category>
            <category><![CDATA[kotlin-coroutines]]></category>
            <dc:creator><![CDATA[Rick Lee]]></dc:creator>
            <pubDate>Wed, 23 Jan 2019 02:04:04 GMT</pubDate>
            <atom:updated>2019-01-23T02:05:14.013Z</atom:updated>
            <content:encoded><![CDATA[<p>Kotlin 1.3 was out late 2018 and one of the major new features is coroutine. Hmm…it’s not really new feature for kotlin, but it was just in experimental state for a very very long period of time and it now becomes stable!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/632/1*aJp-LNY8Zeb5gyCKdEWMfQ.png" /></figure><h3>What’s coroutine?</h3><p>Coroutine is basically a new syntax for async programming. It’s like async-await in javascript and with that we can get rid of those very heavy Future boilerplate code.</p><p>Simple example:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/8635dec09cdad15600a60342a8d97484/href">https://medium.com/media/8635dec09cdad15600a60342a8d97484/href</a></iframe><p>The <strong><em>launch</em></strong> block will launch suspend (async) function in non-blocking manner, so you will see the “Main thread here” shown before the query function is completed.</p><p>Running suspend functions concurrently:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/7f6605e0a06fd112437d2cdd4f14abc6/href">https://medium.com/media/7f6605e0a06fd112437d2cdd4f14abc6/href</a></iframe><p>From the result, you can see the fakeQuery1 and fakeQuery2 have a delay of 3s and 2s, but the total time taken for executing both suspend functions is 3s, so they were running concurrently!</p><h3>Conclusion:</h3><p>There are quite many ways that can do concurrent problem. In the back old day, we did multi-threading, it’s real fast only given you’re a very experienced multi-threading programmer, but with coroutine, the syntax and structure are not much different from normal sequential programming and basically every programmer can master that easily. One more thing, coroutine is very light-weight comparing with threads.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=8eb76af2ce5b" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[React Suspense & code splitting]]></title>
            <link>https://medium.com/@ricklee_10931/react-suspense-code-splitting-df1332f47052?source=rss-88c7c2b846------2</link>
            <guid isPermaLink="false">https://medium.com/p/df1332f47052</guid>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[webpack]]></category>
            <category><![CDATA[react]]></category>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[frontend]]></category>
            <dc:creator><![CDATA[Rick Lee]]></dc:creator>
            <pubDate>Tue, 22 Jan 2019 05:45:52 GMT</pubDate>
            <atom:updated>2019-03-11T11:30:01.652Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/499/1*IqkgHmkCYdoZ1hiQh7J8oA.png" /></figure><p>The bundle size of the modern Single Page Application is usually huge, especially if you include tons of third party libraries. User has to wait until the bundle is fully downloaded, in order to interact with the application. It might be a problem for poor Internet connection.</p><p>Webpack supports code splitting, which can divide the bundle into pieces. Together with the latest React Suspense/lazy feature. Application can load only the necessary part of code the that moment dynamically.</p><p>The following example is created by Create React App and it hides all complexity of the Webpack setup.</p><p>Assume we have 2 components, i.e., ComponentA and ComponentB, and ComponentB will only show when the ComponentA is clicked.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/7b6146ece6e6f8704ac63ebd48001ad8/href">https://medium.com/media/7b6146ece6e6f8704ac63ebd48001ad8/href</a></iframe><p>The full bundle was downloaded when the page was loaded:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/742/1*kvF92bfOTqHtRLMrSlVWdQ.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/743/1*wAlsP4oxY10NDxds8gvunw.png" /></figure><p>Change to load ComponentB dynamically using React.Suspense</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/bb1c852a10c6513e9c91769ecb57f4a7/href">https://medium.com/media/bb1c852a10c6513e9c91769ecb57f4a7/href</a></iframe><figure><img alt="" src="https://cdn-images-1.medium.com/max/742/1*UV1ZAH9CqbFj8fDnaBMK2g.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/741/1*ihOAd8X5-Ce3NPKVkB_sTw.png" /></figure><p>Here we can see the 0.chunk.js and 2.chunk.js were loaded only after the ComponentA was clicked. 0.chunk.js is the ComponentB code and 2.chunk.js is the momentjs library. Thanks for all magic from CRA and React suspense!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=df1332f47052" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>