c4se記:さっちゃんですよ☆

.。oO(さっちゃんですよヾ(〃l _ l)ノ゙☆)

.。oO(此のblogは、主に音樂考察Programming に分類されますよ。ヾ(〃l _ l)ノ゙♬♪♡)

音樂は SoundCloud に公開中です。

考察は現在は主に Scrapbox で公表中です。

Programming は GitHub で開發中です。

Format JSON by jq, on Vim

Vim の buffer の内容を jq で format する。下の記事に書いて在る事でしかないが。

cf. pipe - Piping buffer to external command in Vim - Stack Overflow

大きな JSON を得たがそれが format されてゐない。ざっと目で眺めたいから、jq .に流し込めればよいが、手數が掛かる。この手數を、

  1. Vim を開く
  2. JSONVim の buffer に put する
  3. jq を適用する

でやるのが、escape 要らずで確實に出來、且つ手數が少ないのではなからうか。

目指す command は:!で、これの help は:h :!で見られる。:!の後に shell command を續けられ、實行できる。この command には前に範圍を指定出來、その場合範圍の内容を stdin として shell command に與へ、stdout で範圍を置き換へる。詰まり、

:%!jq .

で buffer の全内容を jq で format 出來る。buffer の一部も指定出來、例へば選擇した範圍を format するならば:'<,'>!jq . (visual mode で選擇してから:!jq .と實行する) を使へる。

以上は Vim だけでなく Evil (Vi layer for Emacs)でも同樣に出來る。

cf. emacs-evil/evil: The extensible vi layer for Emacs.

ヾ(〃l _ l)ノ゙

Monitoring Elixir Plug/Phoenix Web application easy. KomachiHeartbeat v0.1.0 ヾ(〃l _ l)ノ゙

Rails にはKomachiHeartbeatと云ふ何かと有り難い mountable engine が在り、Elixir/Phoenix にも欲しかったので移植した。

KomachiHeartbeat

github.com

Plug 若しくは Phoenix の application の、適当な path にぶら下げて使ふ。例では/opsにぶら下げてある。Phoenix だと router で、

defmodule ExampleWeb.Router do
  use ExampleWeb, :router

  forward("/ops", KomachiHeartbeat)
end

とすると、

  • GET /ops/heartbeat
  • GET /ops/stats

と云ふ二つの endpoint が出來る。heartbeat は 200 ok か 503 error を返す。application が新しい HTTP 接續を受けられるなら 200 ok が返ってくる。受けられないなら timeout するだらう。接續は受けられるが何か問題 (何を確認するかは plugin で擴張する) が在るなら 503 error を返すやうに出來る。

stats は application の統計情報を返せる。default では空っぽで、plugin で返す情報を増やす。

元の Rails のものとの違ひは、収集する情報は全てを plugin で作るやうにしてあり、入れ替へられるようにした。Elixir には Rails と違ひ、「標準の stack」の樣なものは Ecto 位いしか無く、application によって確認すべき事が全く異なるだらうからだ。とは言へ標準の plugin は幾つか作りたいと思ってゐる。

Git repository の名前は Ex-KomachiHeartbeat であるが、これは当然元としたものと區別出來なければならない事と、Max 新幹線の樣な語呂にする爲に suffix ではなく prefix にした。

はい?

こまち (列車) - Wikipedia

Max (鉄道車両) - Wikipedia

(〃l _ l)

Testable readonly ETS. Mnemonics.ExMachina v0.1.0 ヾ(〃l _ l)ノ゙

  • 讀み取り専用
  • on-memory で高速
  • 再起動せずに新しい ver.の data へ入れ替へられる
  • 古い ver.で處理してゐた計算はそのまま古い ver.を讀み出し續けられる
  • heap 領域に cache できる。讀み出した data を snapshot として system 外に持ち運べる
  • parallel

これらを滿たしたMnemonicsと云ふ Elixir の library を以前に作った。無停止 upgrade 出來るActiveHashの樣なものだ。

Mnemonics を使った code を test しやうとする。test で使ふ data は、實働環境から独立である必要が在る、即ち test で使ふ data はは test 内に書かれてあるのが好い。又 test で使ふ data は、他の test からも独立である必要が在る、即ち或る test が書き換へた data が他の test に影響しないのが好い。PostgreSQL 等の DB を使った code を test するには 2 つの方法が在る。ひとつには DB と遣り取りする函數を mock して了ふ。もうひとつは test 毎に一意な data を DB に書き込む。test 毎に一意であればその data は他のどこからも讀み出せない。RDB であれば通常は、一意な primary key を test の外で生成して 與へ、與へられた key の data 以外には手を触れないと取り決めてやる。所謂 test factory だ。Rails/ActiveRecord だとFactoryBotが有名だ。Elixir/Ecto だとExMachinaが有名である。例へばこう使ふ。

defmodule Factory do
  use ExMachina.Ecto

  def user_factory do
    id = sequence("")
    %User{id: String.to_integer(id), name: "user" <> id}
  end
end

defmodule UserTest do
  import Factory

  use ExUnit.Case

  test "authorized?" do
    user = insert(:user)
    assert User.authorized?(user)
  end
end

some_factoryと云ふ函數を定義してやりuse ExMachina.Ectoとしてやると、build(:some)insert(:some)と云ふ函數が使へる樣に成る。

さて Mnemonics ではこれが出來ない。test 毎に一意な data を生成してやるのだが、readonly なので環境に書き込めない。

出來なかった。mock する手も在っただらうとは思ふものの、ETS をまるごと mock するのはダルいので、Mnemonics 側に書き込み出來る穴を空けてやった。この穴は table 毎に 1 つの GenServer であり parallel ではないので本番では使ってはならないが、test で使ふには充分速い。

Mnemonics.ExMachina

github.com

こう使ふ。

defmodule Factory do
  use Mnemonics.ExMachina

  def item_factory do
    id = sequence("")
    %Item{id: String.to_integer(id), name: "user" <> id}
  end
end

defmodule UserTest do
  import Factory

  use ExUnit.Case

  test "drop?" do
    user = insert(:item)
    assert Item.drop?(item)
  end
end

use ExMachina.Ectouse Mnemonics.ExMachinaに變はっただけ。一つの factory に兩方を use する事は出來ないので、併用する時は 2 つ factory を作ってやり、尚且つ import せず full qualified に module 名附きで呼んでやれば好い。

ヾ(〃l _ l)ノ゙

Haskell is good for scripting language ヾ(〃l _ l)ノ゙

Clojure/Haskell の誓ひと云ふのを立ててゐる。個人的な programming を Clojure/Haskell 以外でしないと云ふ誓ひだ。大体の事は置き換へてゆける。Java を使ふところは Clojure に置き換へる。Lisp を使ひたかったし、SuperCollider (Overtone)と Processing (Quil)を同時に扱ふのが簡單であるので、Haskell-like (Eta)ではなく Clojure を使ってゐる。JavaScriptHaskell に置き換へられる。Web front-end 用 framework (Miso)すら在る。

一つ困ってゐて、shell script とその仲間を捨てられずにゐた。ClojureHaskell も shell script を置き換へるのは辛からうと思った。ClojureJVM を起動しなければならないし、又これは JVM に關はる事ではないからできれば Haskell でやりたい。しかし GHC の標準 library では全然足りないから幾つも library を入れ追從しなければならない。と思ってゐた。さういふ時には、Ruby を書いたり Perl を書いたり Crystal を書いたりしてゐた。誓ひは破られたのである。

この度に、少々無理にでも Haskell で軽く scripting できる手法を見附けておくべきだらうと思ひ決めた。GHC の標準 library は貧弱だと思ひ込んでゐたから、その貧弱な標準 library で苦心するか、Stack project を作る事無く Hackage の library を簡單に扱へる方法を組み立てやうと決め、もそもそと調べ出した。

しかし書けたのである。特に苦勞は無かった。runghc も GHC の標準 library も好い仕事をした。皆とりこし苦勞だった。

昔との違ひはDashを使ふ樣に成ってゐた事である。何をするにもその環境の標準 library を全文檢索する癖が附いてゐたから、そんな誤解もしなく成ってゐた。全文檢索は凄い。runghc も頗る速かった。この理由は知らない。

以下が shell script から移してきた短い Haskell script である。git-deployと名附け、git-deploy some_host_on_ssh_config /home/some_userの樣に使ふ。雜な内容から用途の雜さは推して知るべしである。

#!/usr/bin/env runghc

import System.Environment ( getArgs, getExecutablePath )
import System.FilePath ( takeBaseName )
import System.Posix.Directory ( getWorkingDirectory )
import System.Process ( readCreateProcess, shell )
import Text.Printf ( printf )

main :: IO ()
main = do
  args <- getArgs
  case args of
    host:remoteDir:_ -> deploy host remoteDir
    _ -> help

help :: IO ()
help = putStr $ unlines [ "Help: deploy HOST REMOTE_DIR" ]

deploy :: String -> String -> IO ()
deploy host remoteDir = do
  projectName <- fmap takeBaseName getWorkingDirectory
  sh $ printf "git archive -9 -o /tmp/%s.tar.gz --prefix %s/ HEAD" projectName projectName
  sh $ printf "scp /tmp/%s.tar.gz %s:%s/%s.tar.gz" projectName host remoteDir projectName
  sh $ unlines
    [ (printf "ssh %s -K 'bash -s' <<EOF" host)
    , (printf "cd %s" remoteDir)
    , (printf "tar xzf %s.tar.gz" projectName)
    , "EOF"
    ]

sh :: String -> IO ()
sh command = do
  putStrLn $ "+" ++ command
  out <- readCreateProcess (shell command) ""
  putStrLn out

-- vim:set ft=haskell:

今困ってゐるのは、Haskell の文件を開くと Emacs (Evil) が固まる事。kill するしか無くなってしまふ。代りに Vim を使ってゐるが…。

ヾ(〃l _ l)ノ゙