Sunday, June 04, 2017

I can't use alt key combos in netbeans under os x

found this stack overflow answer useful:

download this keyboard layout for us english

copy it to ~/Library/Keyboard\ Layouts/

go keyboard system preference panel, under input sources tab, click + to add the layout.

however, alt key combos fires they key twice, so still useless.


zpresent.el is an emacs package for presentation

just create an org file and m-x zpresent will start the presentation.

(setq mode-line-format nil) to hide mode line

to do it globally, use (setq-default mode-line-format nil)


I like erlang/elixir's pattern matching (comes from prolog, but prolog is two-way unification)

I want to use them more when I do clojure, I'm ready to use core.match and defun heavily.

also studying clara-rules: Forward-chaining rules in Clojure.


reading Reactive Programming with RxJava, slowly.

rx started at microsoft, then those people went to netflix, facebook etc. rxjava was created by netflix.

the core of rxjava is Observable, and Observable is about pushing.

in contrast to Iterable (pulls)

I like the explaination they gave on performance of nginx vs tomcat:

event loop has performance advantage because hot threads, tomcat starts new thread on new request, which is cold and of course it takes time to warm up.

Friday, June 16, 2017

SREcon17 Asia/Australia has some pretty good topics.

I watched InnoDB to MyRocks Migration in Main MySQL Database at Facebook, learned more about MySQL internals.

I want to try MyRocks simply because it saves more space than compressed InnoDB, which is the biggest pain point on a $5 digitalocean droplet.

this guide teaches you how to build it under ubuntu and migrate from innodb to myrocks

further reading: MyRocks: A space- and write-optimized MySQL database


reading Understanding ECMAScript 6: The Definitive Guide for JavaScript Developers, quite good.

I finally understand yield after reading this book:

yield stops the function right after it's being called, so this code

let a = yield 1;
the assignment will be executed on the next yield, but you can call the next yield with next(5), so when the assignment happens, a will be 5

anyways, es6 is very different from the javascript I'd learned before (I read quite a few javascript books). but it's better, like kotlin to java.


I watched Anthony Marcar - Clojure At Scale @WalmartLabs, he mentioned component helps them to scale.

then I watched Stuart Sierra - Components Just Enough Structure

so in clojure, there're few libraries to help you maintain states:

there're tons of discussions on component and mount:

I picked mount, I don't mind to use global defs, I just don't want to pass extra parameters around.

Recently I've been using a lot mount and core.match, finally I can produce some clojure codes which is easy to read and easy to maintain.


read Reducers, transducers and core.async in Clojure, I've been working on some ETL tasks

so I watched Simplifying ETL with Clojure and Datomic - Stuart Halloway

I think core.async and transducers are good fit for etl jobs, I'm working on porting some of tasks to channels

I also found a good resources on core.async: Eric Normand's Core.async Patterns, and codes on lispcast/core-async-patterns.


some good reads:

Saturday, June 17, 2017

got my vortex core keyboard, it's very nice looking

however, 47 keys are not easy to use. the biggest problem with it is how to make pn and left space less wasted.

even with the latest firmware, you can only switch pn OR fn, not both.

I tried swapped pn and fn, and set left space as alt, but didn't work well.

I finally mapped left space as fn, and left pn being wasted.

the final version is like this:

|------------+-------------------+----------|
| new key    | current key       | output   |
|------------+-------------------+----------|
| row 1      |                   |          |
|------------+-------------------+----------|
| fn + esc   | fn1 + shift + esc | ~        |
| fn + q     | fn1 + shift + tab | !        |
| fn + w     | fn1 + shift + a   | @        |
| fn + e     | fn1 + shift + s   | #        |
| fn + r     | fn1 + shift + d   | $        |
| fn + y     | fn1 + shift + g   | ^        |
| fn + u     | fn1 + shift + h   | &        |
| fn + i     | fn1 + shift + j   | *        |
| fn + o     | fn1 + shift + k   | (        |
| fn + p     | fn1 + shift + l   | )        |
| fn + del   | fn1 + m           | [        |
| fn + bs    | fn1 + ,           | ]        |
|------------+-------------------+----------|
| row 2      |                   |          |
|------------+-------------------+----------|
| fn + f     | fn1 + shift + f   | %        |
| fn + j     | fn1 + n           | /        |
| fn + k     | fn1 + ;           | -        |
| fn + l     | fn1 + enter       | =        |
| fn + ;     | fn1 + b           | '        |
| fn + enter | fn1 + .           | \        |
|------------+-------------------+----------|
| row 3      |                   |          |
|------------+-------------------+----------|
| fn + c     | fn + u            | pageup   |
| fn + v     | fn + o            | pagedown |
|------------+-------------------+----------|
| row 4      |                   |          |
|------------+-------------------+----------|
| left space | fn                | fn       |
|------------+-------------------+----------|

note,

  • always use right shift/menu/right alt/right ctrl as up/down/left/right (enabled by left win + left alt + right space)
  • once mapped to fn + key, it also mapped shift + fn + key autometically.
  • fn + t, fn + g and fn + b are for time delays, can not be programmed.

I also setup dedicated layer for numbers and arrows.

Wednesday, June 21, 2017

reading MongoDB in Action, Second Edition

there're lots of bad comments on mongodb, however, after read two parts of this book, I found mongodb is a really powerful tool.

I can also see they've been improved quite a lot in recent verisons.


there're few ways to do authentication for aws api gateway calls mentioned in their documentation

however, actually only two are useful for client side javascript:

if you're willing to do a registration flow on cognito, it's the best way. cognito issues token and verify it for you.

otherwise, you'll need to use a lambda to verify tokens issued by your backend or something like auth0 (auth0 can verify tokens for you as well)

some notes from implementing the lambda:

  • don't use Authorization header (which is default value for a auth lambda), seems it conflicts with aws connections, just use a custom one like Auth to save yourself some trouble.
  • curl is not working. api gateway requires https client supports sni, looks like my curl doesn't support it.
  • they have specific input and output format

also, for lambda using proxy integration, you also need to follow their output format


about aws lambda to connect database, connection pool is a problem, because there's no connection pool.

lambda should be stateless, it can die and restart anytime. so connection pool doesn't make sense to it.

the best way is use a rest api wrapper, but usually it will be difficult to find library to do connection this way.

mongodb article uses a cached connection declared outside of handler function.

which is the way I've been using now: use atom to hold the connection state.

I think for aws dynamodb they're using rest api endpoints. so no this problem.


about dynamodb, some notes too:

  • it supports conditional upsert, which is nice
  • supports secondary index keys
  • basicially you'll need to involve the primary key all the time, key-value storage ...
  • no aggregation, if you need it, dynamodb probably not for you.

the query is quite limited and it requires more effort on application side.


for me, serverless is still quite painful to work with: too many small pieces, hard to test, it scales well (means you don't want it connecting to your existing infrastrucure/applications, unless your application scales that well too)

Saturday, June 24, 2017

I'm wondering why dynamodb only said they're doing partitioning, instead of sharding.

I did some search, partitioning is a more generic term, horizontal partitioning is one of partitioning type, and sharding is basically horizontal partitioning except:

Horizontal partitioning can be done both within a single server and across multiple servers, the latter often being referred to as sharding.

still didn't get the answer, dynamodb obviously is sharding, but why only term partitioning is used?


I'm looking for a better way to handle exceptions in clojure, I found MichaelDrogalis/dire: Erlang-style supervisor error handling for Clojure useful.

let's take a look at its self correcting example:

(ns mytask
  (:require [dire.core :refer [with-handler supervise]]
            [fs.core :refer [touch]]))

(defn read-file [file-name]
  (slurp file-name))

(with-handler #'read-file
  java.io.FileNotFoundException
  (fn [exception file-name & _]
    (touch file-name)
    (supervise #'read-file file-name)))

(supervise #'read-file "my-file")

which is super nice.

Sunday, June 25, 2017

I usually don't write tests, but Midje is what I will use if I have to.

just add this to project.clj:

:profiles {:dev {:dependencies [[midje "1.8.3"]]}}

test files locates:

├── src
│   └── quux
│       └── core.clj
└── test
    └── quux
        └── core_test.clj

a simple test is like:

(ns myproject.core-test
  (:require [midje.sweet :refer :all]
            [clojure.string :as str]))

(fact "simple test"
      (str/split "a/b/c" #"/") => ["a" "b" "c"])

you can run tests in cider repl too:

user> (use 'midje.repl)
user> (load-facts) ;; load all facts
user> (check-facts) ;; recheck facts
user> (autotest) ;; watch file changes and load facts
user> (autotest :stop) ;; stop autotest, also has :pause, :resume

to run test from lein, add lein-midje to your ~/.lein/profiles.clj first:

{:user {:plugins [[lein-midje "3.2.1"]]}}

then you can run

$ lein midje // load facts
$ lein midje :autotest // watch file changes and load facts

I have to say the autotest feature is very useful.


to exclude all clj/cljs/cljx files in a uberjar, add this line to project.clj:

  :uberjar-exclusions [#"\.(clj[x|s]?|java)"]

Blog Archives

Search Blog: