株式会社クリアコード > ククログ

ククログ


ノータブルコード1 - printfの縦揃え

リーダブルコードの解説の著者の須藤です。リーダブルコードの本編ではプログラマそれぞれがリーダブルなコードを書く方法を紹介しています。リーダブルコードの解説ではチームでリーダブルなコードを書く方法を紹介しています。

では、その次のステップはなんでしょう。それは「チーム外とリーダブルコードの知見を共有する」です。情報を提供するところに情報は集まります。自分たちがリーダブルコードの知見を発信することで知見が集まります。集まるのを待つだけではなく自分から知見を探しにいけばさらに知見を集められます。チーム内だけで知見を共有していると、限られたコンテキストでの知見しか得られなくなってしまいます。チーム外の知見も活用することでチームに新しい知見を導入できます。

たとえば、Ruby on Railsを使ってWebアプリケーションだけを書いている場合はそのコンテキストの知見ばかり集まります。しかし、その知見は、Pythonで機械学習するコードを書いたときに得られる知見とは違います。Pythonで機械学習するコードを書いたときに得られる知見のうちRuby on Railsを使ってWebアプリケーションを書いているときに活かせる知見もあるものです。違うコンテキストの知見を集められればもっとリーダブルなコードを書けるようになります。

実際に自分が違うコンテキストのコードを書かなくても、違うコンテキストで書かれたコードを読むだけでも知見を得られます。(もちろん、自分が書いた方が得られる知見は大きいです。)そのため、クリアコードのメンバーは他の人が書いたコードを読んで学んでいます。野生のリーダブルコードを見つけて学んでいるということです。クリアコードが大事にしているフリーソフトウェアには「プログラムがどのように動作しているか研究し、必要に応じて改造する自由 (第一の自由)」があるので野生のリーダブルコードを学び放題です。

前置きが長くなりましたが、クリアコードのメンバーが普段やっている「他の人が書いたコードから学んだこと」を「ノータブルコード(Notable Code)」としてこのブログで紹介することにしました。前から社内では紹介していたのですが、社内で閉じる必要はないので公開している場所で紹介することにしました。

「ノータブルコード」という名前にした理由は次の通りです。

  • 「リーダブルコード」っぽい!(語感が似ている)
  • 「よい悪い」というより「単に私はここに注目したよ!」というだけだから(「note」ってそういうニュアンスだよね?)
    • 「notable」には「重要な」という「よい」ニュアンスがあるみたいなので本当はアレなんですけど。。。

それでは最初のノータブルコードを紹介します。

Apache ArrowのRのLinux向けパッケージを改良するプルリクエストで見つけたものです。

sprintfを使って文字列をフォーマットしているRのコードです。Rのコードですが、sprintfはいろんな言語にある機能なので、Rを読み書きできない人でも読めるはずです。

https://github.com/apache/arrow/pull/6068/files#diff-3875fa5e75833c426b36487b25892bd8R153-R155

  env_vars <- sprintf(
    "SOURCE_DIR=%s BUILD_DIR=libarrow/build DEST_DIR=%s CMAKE=%s",
    src_dir,                                dst_dir,    cmake
  )

sprintfはフォーマット文字列に実際の値を埋め込んで最終的な文字列を生成しますが、どの値がどこに対応するかわかりにくくなりがちです。このコードでは縦に埋め込み場所と埋め込まれる値を揃えて対応をわかりやすくしています。

他のやり方として、文字列内に式を埋め込む方式(Rubyなら"SOURCE_DIR=#{src_dir}"と書く)や、埋め込み場所に名前を使う方式(Rubyなら"SOURCE_DIR=%{src_dir}" % {src_dir: src_dir}と書ける)がありますが、このスタイルは初めてみました。1行が長すぎると使えないとか、埋め込む値の式が長いと使えないとか使える機会は限定される気がしますがおもしろいなぁと思いました。

おもしろくて思わずコメントしてしまいました。このコードを書いた人によるとリーダブルなコードになるようにいろんな方法を実験していたとのことでした。やっぱり工夫して書いたものだったんですね。

2020年はみなさんも気になったコードを「ノータブルコード」として共有してみませんか?

2020-01-14

ノータブルコード2 - 斬新なコメントでコードの可読性を高める

この新しいコーナー「ノータブルコード」では、私たちが開発の折々に目にした興味深いコードをご紹介しています。世の中の実際のプロジェクトから、興味深い素材を肩の凝らない形でご紹介していきたいと思いますので、楽しみにしていてください。

Brubeck - 創造的なコメントで見通しを良くする

第2回目に紹介するのは、GitHubが開発したStatsD互換サーバー Brubeck からの一コマです。

int brubeck_statsd_msg_parse(struct brubeck_statsd_msg *msg, char *buffer, char *end)
{
    *end = '\0';

    /**
     * Message key: all the string until the first ':'
     *
     *      gaugor:333|g
     *      ^^^^^^
     */
    {
        msg->key = buffer;
        msg->key_len = 0;
        while (*buffer != ':' && *buffer != '\0') {
            /* Invalid metric, can't have a space */
            if (*buffer == ' ')
                return -1;
            ++buffer;
    ...

https://github.com/github/brubeck/blob/master/src/samplers/statsd.c#L140-L241

このコードが面白いのは、ずばりコメントの付け方です。

そもそもC言語でパーサを書くのは、非常に面倒な仕事です。RubyやPythonなどのより高級な言語と比べると、その手間のかかり具合は歴然としています。例えば、メッセージを単語に分割する処理ひとつ取っても、Pythonならmsg.split(" ")と書けば簡潔に記述できるのに対して、C言語だと「文字列の先頭から空白文字を探索し、見つかったらノードを初期化して連結リストに追加して次に進む。見つからなければ...」というように 『手続きの積み重ね』 として表現する必要があります。

これは書くのも面倒なら、読むのも大変なコードです。プログラムの作成者の意図は手続きの積み重ねの中に隠れてしまっているので、他の開発者はコードを地道に追うことでそれを読み取るしかないからです。

Brubeckのコードが斬新なのは、このC言語の技術的な制約をコメントの付け方によって回避している点です。冒頭にコードの一部を引用していますが、Brubeckの開発者はブロックごとに「いまここではプロトコルのこの部分を解析しています」というコメントを付与することで、書き手の意図を読み手に伝える戦略を選びました。

ポイントをはっきりさせるため、コードの一部を取り出して構成を以下に図示します。冒頭のコメントが後続する処理の宣言になっていることが明解に見て取れると思います。

Brubeckのコード解説

私たちは、このコードに感銘を受けたので、自分たちのStatsDパーサでも同じようなブロックコメントを付けることにしました

開発の現場では、時としてコメントは「おまけ」として扱われがちですが、創造的な使い方をすることで、コードの読みやすさを一変させることができるのだ、というのが今回の連載の要点です。

補足: 関連するテクニックについて

このBrubeckの手法に似ているものとして、コミットメッセージの中で記号を使って、変更内容を視覚的に示すというテクニックがあります。

こちらについては、過去記事「わかりやすいコミットメッセージの書き方」 の中で紹介しているので(記事中の「英語だけで表現することにこだわらない」の節を参照)、興味のある方はご一読ください。

2020-01-15

Prometheus Meetup Tokyo #3でLTをしました

はじめに

Prometheus Meetup Tokyo #3でLTをしてきた畑ケです。
Prometheusは近年注目されるメトリクスモニタリングツールです。特徴としては非常にスケーラビリティが高く、Pull型でメトリクスを収集するため、Prometheusのインスタンス1つで1万インスタンスのサーバー群を監視できます。このPrometheus Meetup Tokyo #3ではPrometheus本体というよりもそれを取り巻くエコシステムを対象としたミートアップでした。

筆者は最近Prometheusのエコシステムの一つでGrafana Labが出しているLokiというログ基盤を触ったことがあり、触った時の成果の一つがLTのネタになるのではないかとのことでLTに応募してみたところ、LTに採択されました。

イベントの内容

まず他の方のされた発表をご紹介します。

Remote Write API と Thanos を活用したメトリクス永続化
  • Moto Ishizawa 氏(@summerwind), Z Lab Corporation

コンテナを基盤とする環境でPrometheusを運用していると、例えば、k8sのクラスターを作り直したときにPrometheusで収集したメトリクスが消失してしまう問題があるそうです。
このメトリクスがk8sクラスターに紐づいてしまっている問題を解消するのに永続化ストレージを採用し、永続化を試みていました。ThanosというPrometheusを高可用性にし、長期間のログ保存を可能にするソフトウェアを用いて方法をPrometheusで収集したメトリクスを永続化する方法を丹念に調査していた発表でした。

Victoria Metricsで作りあげる大規模・超負荷システムモニタリング基盤
  • 入江 順也 (GitHub: inletorder)氏, 株式会社コロプラ

Victoria MetricsというこちらもPrometheusで収集したメトリクスを長期間永続化するソフトウェアを使って、Prometheusを高負荷環境にも耐えられえるようにした試行錯誤を発表されていました。このソフトウェアにたどり着くまでにいくつかのPrometheus関連のメトリクス永続化ストレージを試されたそうです。Victoria Metricsはいくつかのコンポーネント(VMStorage, VMSelect, VMInsert)に分かれており、そのうちVMStorageは持つデータによって状態を持つのでk8sではStatefulSetとしてデプロイする必要があるそうです。k8sのマルチテナント構成では合計1万Pod以上の監視を安定的に行えるようになったそうです。

次世代のログ基盤 Grafana Lokiを始めよう!
  • 仲亀 拓馬氏(@kameneko1004, さくらインターネット 株式会社), 上村 真也氏(@uesyn, Z Lab Corporation)

本ククログで何回か筆者が開発者視点で取り上げているGrafana Lokiについての発表です。Lokiについてのデモを通じてどのようなソフトウェアなのかを解説するのが前半の発表でした。後半はpromtail特集でした。promtailはpromtail.yamlにてPrometheusの設定と同様の設定を流し込むことで設定できるそうです。Prometheusと同様にGrafana Lokiも時系列データを保持するのにTSDBを使用しており、これに入れたデータをクエリするのにラベルが必要になるのですが、このラベル設計がうまくないと後に目的の時系列データをクエリするのに苦労するようです。

LTの内容

以下は筆者が行ったLTの内容です。

Grafana Lokiの開発元にFluent BitのGo製のLokiプラグインをフィードバックしてみた話をしました。
このFluent BitのGo製LokiプラグインはFluent BitからGrafana Lokiに転送する方法をまとめたときに紹介しました。
Grafana Lokiは開発が活発なソフトウェアということもあり、ドキュメントがあまり見当たりませんでした。
そのため、promtailがやっていることをソースコードを見つつFluent BitのGo製Lokiプラグインとして仕上げました。

LTではフリーソフトウェアにフィードバックする作法を軽く触れました。
Grafana Lokiもフリーソフトウェアです。フリーソフトウェアの開発は通常開発者同士が同時に同じ場所に集まっているのではなく、住んでいる国や文化、ひいては暮らしているタイムゾーンも異なる場合があります。
フィードバックするには言葉で説明しなければいけません。

まずは、動機や今困っていることを説明します。

  • なぜこの機能が必要か?なぜこの問題を報告したのか?
  • このIssueチケットやプルリクエストでは何を問題にするのか?

プルリクエストは小粒なtypo修正ではない限り、Issueチケットに関連付けられるものとして出す方が良いと筆者は考えています。しかし、この方針はプロジェクトによって異なります。プルリクエストを出す時はプロジェクトの方針を確認してみてください。

  • プルリクエストでは方針を議論するよりも提出したパッチが前もって議論した方針に合っているか、このプロジェクトに受け入れられる品質となっているか?を議論する場だからです。

プルリクエストやIssueチケットにチェックリストが付いているのであれば一通り確認すべきです。

  • 問題が発生している報告者の環境を開発者が再現するには十分な情報が書き込まれている必要があります。
  • よいIssueチケットは開発者が見た時にどのようにすればこの問題が再現できるか?がチケットを見ただけで理解できるチケットです。
  • レビュアーが見るべき箇所が発散しておらず、実現したい機能が実現できているか、パッチの変更は妥当かのレビューに集中できるものがよいプルリクエストです。

Grafana LokiにFluent BitのGo製プラグインをフィードバックしてみたところ、ユーザーもそこそこ出てきたようです。

Grafana Loki自体は一個のバイナリですし、promtailもバイナリ一個で済みます。そのため、Dockerコンテナに載せやすいです。
これらの特徴に加え、Grafana LokiはPrometheusファミリーということもありk8sと非常に親和性がよいです。

k8sに載せるにはまずDockerコンテナ化しないといけないということで、Dockerコンテナ化の要望が新たにIssueチケットとして切られました。
このFluent BitのGo製のLokiプラグインDockerイメージもGrafana Lokiの公式イメージとして提供されることになりました。

k8sでは複数のサービスを連携して動作させる必要がありますが、手動で連携させるには面倒な場合があります。
この煩雑さを解決するソフトウェアはいくつか出ています。Grafana Lokiの開発元からはこの煩雑さを解決するソフトウェアのhelmを用いたFluent BitのGo製Lokiプラグインのレシピが提供されることになりました。

筆者はこのhelmのレシピがきっかけでk8sをより深く理解することになりました。自身の成果をフリーソフトウェアにフィードバックするだけで終わりではなく、フィードバックすることにより学びのきっかけを頂けました。

まとめ

日本ではあまり事例の少ないFluent BitとGrafana Lokiを題材にしてフリーソフトウェアの開発元にフィードバックする作法をLTしました。
フリーソフトウェアの問題を手元で回避するのではなく、開発元にフィードバックするのはクリアコードが普段実践している開発スタイルです。

フリーソフトウェアを普段使っている方でもフリーソフトウェアの開発元にフィードバックする方法が分からず、手元で問題を回避していたり、手元でパッチを持ったままになっている方もいると思います。
その時には本記事のフリーソフトウェアであるGrafana Lokiの開発元へフィードバックした事例をヒントにしてフィードバックに挑戦してみてはいかがでしょうか?

また、フリーソフトウェアの開発にまだ参加したことがない人を対象にしてOSS Gateワークショップを開催しています。こちらも併せて検討してみてください。

タグ: Fluentd
2020-01-17

GitHub Actionsを使ったパッケージ作成の自動化

2019年の11月にGitHub Actionsが正式にリリースされました。
GitHub ActionsはGitHubに組み込まれたCI/CD機能でpush等のGitHub上のイベントをトリガーに任意のアクションを実行できるものです。
GitHub ActionsではDockerが使用できるので、様々な環境上でテストの実行やビルドなどができます。

CIサービスは、他にもAppVeyorやTravis CIがありますが、AppVeyorは無料のプランだと、ワーカーがプロジェクトにつき1つなので、Groongaのように複数のパッケージを作成するためにジョブが多くなるプロジェクトだと、ビルドとテストの完了に時間がかかってしまい効率的ではありませんでした。
GitHub Actionsでは、リポジトリーにつき20まで並列で実行できます。

また、Travis CIでは、ビルドした成果物を保存する場所がデフォルトで用意されていないため、正常にビルドできるかの確認やテスト実行はできますが、リリース用のパッケージを作成して置いておくということがやりにくいです。
GitHub Actionsではアクションを実行した結果、生成されたファイルを置いておく場所がデフォルトで用意されているため、GitHub Actions上でパッケージを作成し、作成したパッケージを取得してリリース用のパッケージとしてアップロードするということがやりやすいです。

上記のようなメリットがあったため、Groongaプロジェクトでは、CI/CDをTravis CIやAppveyorからGitHub Actionsへ移行しています。

いままで、GroongaやMroonga、PGroongaのパッケージは開発者の手元でビルド、署名、アップロードを実施していました。
GroongaとMroongaは毎月末にリリースがあるため、毎月末に開発者はパッケージを作る作業を実施しなければなりません。
また、この際にパッケージの作成に失敗するような問題が発覚すると、問題の修正作業にも追われることになります。

GitHub Actionsはpushトリガーでアクションを実行できるので、変更がリポジトリにpushされた段階でパッケージ作成することで、問題の早期発見に繋がり、問題を発生させた変更もすぐに特定できます。
また、GitHub Actionsでパッケージを作成すると開発者はパッケージを署名、アップロードするだけでよくなるので、毎月発生したパッケージ作成時間をなくし、その時間を別の作業に充てることができます。

GitHub Actionsを活用すると、上記のような様々なメリットが発生するので、GroongaとMroonga、PGroongaのパッケージの作成をGitHub Actionsで行うようにしました。この記事は、その過程で得た知見を共有するために記載しています。

まずは、GitHub Actionsの使い方について記載します。

使い方

GitHub ActionsのアクションはYAML形式で記述します。
YAML形式なので、GitHub上でコードとして管理できます。

ここからは、Groongaのパッケージ作成のアクションを例に説明していきます。
Groongaのパッケージ作成のアクションは、以下の場所にあります。

https://github.com/groonga/groonga/blob/master/.github/workflows/package.yml

トリガー

何のイベントをトリガーにしてアクションを実行するかを決めるには、on:を使います。
Groongaのアクションではpush毎にアクションが実行されてほしいので、on:にはpushを指定します。

on:
  push:

GitHub Actionsでは、イベントが起こった対象を指定することができます。
上記のように定義すると、リポジトリーのどのブランチ、タグにpushされてもアクションが実行されます。

全てのブランチやタグが対象ではなく、特定のブランチ、タグにpushされたときだけアクションを実行したい場合は以下のようにします。

on:
  push:
    branches:
      - branch
    tags:
      - tag

push等のイベントトリガーではなく、定期的に実行したいアクションがあるケースもあります。
その場合には、schedule:を使用します。

schedule:の書式はcronの書式で指定できます。ここで指定した時刻はUTCなので、UTCと時差がある日本の場合は時差を考慮に入れて設定する必要があることに注意してください。

Groongaでは以下のように設定し、毎朝9時にアクションが実行されるようにしています。

  schedule:
    - cron: |
        0 0 * * *

onに指定できるイベントは他にもあり、以下のページにまとまっているので、必要に応じて参考にしてください。
https://help.github.com/en/actions/automating-your-workflow-with-github-actions/events-that-trigger-workflows

アクションの定義

実行するアクションはjobs:という単位で定義できます。
複数のジョブを作成してそれぞれ並列に実行することもできますし、あるジョブの完了を待ってから実行するというようにジョブ同士の依存関係を定義することもできます。

Groongaでは、現状、パッケージを作成するというアクションのみを行っていますので、以下のようにbuildというジョブを1つだけ定義しています。

jobs:
  build:

ジョブの中ではいくつかのステップに分けてアクションを定義します。
GitHub Actionsのジョブはステップごとに成功、失敗を表示するので、ジョブをステップに分割しておくと、ジョブが失敗したときの原因特定が容易になります。

Groongaでは、パッケージ作成を以下のステップに分割して実行しています。

  • 依存パッケージの配置
    • aptを用いたインストール
    • pip3を用いたインストール(ドキュメントビルド用に使うSphinxをインストールしています)
    • パッケージのビルドに必要なソースコードをClone
  • configureの生成
  • ソースアーカイブ作成用にconfigure実行
  • ソースアーカイブをビルド
  • debian/changelogの更新
  • Docker上でパッケージをビルド
  • ビルドされた成果物をGitHubへアップロード

具体的には以下のように定義しています。
name:で分割したステップに名前をつけます。
run:で実行するアクションを定義します。

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@master
      - name: Install dependencies
        run: |
          sudo apt update
          sudo apt -V install \
            autoconf-archive \
            bison \
            devscripts \
            python3-pip \
            ruby
      - name: Install Sphinx
        run: |
          sudo pip3 install -v sphinx
      - name: Clone dependencies
        run: |
          cd ..
          git clone --depth 1 https://github.com/groonga/groonga.org.git
          git clone --depth 1 https://github.com/clear-code/cutter.git
      - name: Generate configure
        run: |
          ./autogen.sh
      - name: Configure for archive
        run: |
          ./configure \
            --enable-document \
            --enable-mruby \
            --with-cutter-source-path=../cutter \
            --with-groonga-org-path=../groonga.org \
            --with-ruby
      - name: Build archive
        run: |
          make dist
      - name: Update version
        run: |
          OLD_RELEASE=$(grep -E -o '[0-9.]+' packages/debian/changelog | \
                          head -n1)
          OLD_RELEASE_DATE_FULL="$(grep '^ -- ' packages/debian/changelog | \
                                     head -n1 | \
                                     sed -E -e 's/ -- .+<[^>]+>  //')"
          OLD_RELEASE_DATE=$(date --date="${OLD_RELEASE_DATE_FULL}" +%Y-%m-%d)
          make update-latest-release \
            OLD_RELEASE=${OLD_RELEASE} \
            OLD_RELEASE_DATE=${OLD_RELEASE_DATE} \
            NEW_RELEASE_DATE=$(date +%Y-%m-%d)
      - name: Build with docker
        run: |
          cd packages
          rake ${{ matrix.rake_arguments }}
        env:
          APACHE_ARROW_REPOSITORY: ../../arrow
      - uses: actions/upload-artifact@master
        with:
          name: packages-${{ matrix.id }}
          path: ${{ matrix.repositories_path }}

どのOSでアクションを実行するかはruns-on:で指定します。Groongaではruns-on:ubuntu-latestと定義して、Ubuntuの最新版でアクションが実行されるようにしています。これ以外にも、windows-latest(Windows Serverの最新版)やmacos-latestなどがサポートされています。

実行するコマンドはruns-on:で定義したOSに応じて定義する必要があります。Ubuntuでアクションを実行する場合は、デフォルトでBashが使われるので、Bashで実行できるコマンドを使って定義しています

windows-latestを指定した場合は、デフォルトでアクションがPowerShellで実行されるので、アクションはPowerShellで実行できるコマンドで定義する必要があります。(コマンドプロンプトを使うように指定することもできます。)

アクションを実行するシェルの指定については、以下のページにも説明があるので、必要に応じて参照してください。
https://help.github.com/en/actions/automating-your-workflow-with-github-actions/workflow-syntax-for-github-actions#using-a-specific-shell

GitHub Actionsでは、よくある処理をまとめて公開共有することが可能で、それらの処理はsteps:の中で呼び出せます。
Groongaでは、リポジトリからソースコードをチェックアウトするのにactions/checkoutを、ビルドしたパッケージをアップロードするのにactions/upload-artifactを使用しています。

actions/checkout@以下にチェックアウトしたいタグやブランチを指定することができます。Groongaでは、masterのソースコードを使いたいので- uses: actions/checkout@masterと指定しています。

actions/checkoutactions/upload-artifact以外にも様々な処理がactionとして以下のURLで公開されています。
https://github.com/marketplace?type=actions

複数の環境でアクションを実行する

複数の環境(複数のOSであったり、ソフトウェアの複数のバージョン)に対して同じアクションを実行したいケースがあります。
もちろん、それぞれの環境用にワークフローを定義しても良いのですが、同じアクションが複数のワークフローにあると、修正漏れが発生しやすくなってしまい、メンテナンスが煩雑になります。

同じアクションを複数の環境で実行したい場合は、matrix:という定義が使えます。

Groongaも各OS毎にパッケージを作成するため、このmatrix:を使ってDebianの各バージョン(stretchの32bit, 64bit、busterの32bit, 64bit)、CentOSの各バージョン(CentOS 6,7,8)に対して同じアクションを実行しています。

具体的には以下のように定義しています。

    strategy:
      matrix:
        label:
          - Debian GNU/Linux stretch amd64
          - Debian GNU/Linux stretch i386
          - Debian GNU/Linux buster amd64
          - Debian GNU/Linux buster i386
          - CentOS 6
          - CentOS 7
          - CentOS 8
        include:
          - label: Debian GNU/Linux stretch amd64
            id: debian-stretch-amd64
            rake_arguments: apt:build APT_TARGETS=debian-stretch
            repositories_path: packages/apt/repositories/
          - label: Debian GNU/Linux stretch i386
            id: debian-stretch-i386
            rake_arguments: apt:build APT_TARGETS=debian-stretch-i386
            repositories_path: packages/apt/repositories/
          - label: Debian GNU/Linux buster amd64
            id: debian-buster-amd64
            rake_arguments: apt:build APT_TARGETS=debian-buster
            repositories_path: packages/apt/repositories/
          - label: Debian GNU/Linux buster i386
            id: debian-buster-i386
            rake_arguments: apt:build APT_TARGETS=debian-buster-i386
            repositories_path: packages/apt/repositories/
          - label: CentOS 6
            id: centos-6
            rake_arguments: yum:build YUM_TARGETS=centos-6
            repositories_path: packages/yum/repositories/
          - label: CentOS 7
            id: centos-7
            rake_arguments: yum:build YUM_TARGETS=centos-7
            repositories_path: packages/yum/repositories/
          - label: CentOS 8
            id: centos-8
            rake_arguments: yum:build YUM_TARGETS=centos-8
            repositories_path: packages/yum/repositories/

strategy:の中にmatrix:を定義します。matrix:の中に変数を定義してそれをsteps:の中で${{matrix.xx.xx}}の形で参照できます。

例えば、Groongaの場合各OS向けのパッケージでビルドしたパッケージの格納場所が異なるため、${{ matrix.repositories_path }}を参照して各OSごとのパッケージをアップロードできるようにしています。

${{ matrix.repositories_path }}とすると、matrix:の定義の中にあるrepositories_path:を参照するので、

      - uses: actions/upload-artifact@master
        with:
          name: packages-${{ matrix.id }}
          path: ${{ matrix.repositories_path }}

は、packages/apt/repositories/packages/yum/repositories/配下のファイルをアップロードしていることになります。

まとめ

Groongaのパッケージ作成に使っている内容を中心にGituHub Actionsを使ったパッケージ作成の自動化の方法について記載しました。
GitHub Actionsに興味はあるが、使っていないという方は、この記事に記載されている内容を参考にして自身のプロジェクトで使用してみてはいかがでしょうか。

タグ: Groonga
2020-01-23

2020-03-12開催のRubyセミナー松江で講演予定:「Rubyと仕事と自由なソフトウェア」

株式会社クリアコード代表取締役の須藤です。

2020-03-12開催のRubyセミナー松江で「Rubyと仕事と自由なソフトウェア」というタイトルの話をします。松江に住んでいる人も松江に住んでいない人も私のファンの人は来てね。

Rubyアソシエーションの前田さんに声をかけてもらえたので快諾しました。前田さんに声をかけてもらえてうれしかったです。

主な参加者は「業務でRubyを使っているプログラマ」で内容はまかせてくれるということだったので「Rubyと仕事と自由なソフトウェア」にしました。業務でRubyを使っているプログラマには自由なソフトウェアのことを考えて欲しいなと思ったからです。

前に似たような話をしたことはあったかな?と思い返してみると関西Ruby会議2017での「株式会社クリアコード」が少し近いかも。が、なんか、こういう感じじゃなくて、プログラマが活用できるような話にできるといいな。なぜ、オープンソースは自由ソフトウェアの的を外すのかのような内容を少しでも伝えたいな。

松江でみなさんに会えることを楽しみにしています!

2020-01-24

第28回 中国地方DB勉強会 in 岡山:Amazon RDS + Amazon EC2 + ロジカルレプリケーションを使った低コスト高速全文検索 #ChugokuDB

2020年1月25日(土)に第28回 中国地方DB勉強会 in 岡山が開催されました。
私は、昨年の2019年11月に行われた PostgreSQL Conference Japan 2019 の内容(「Amazon RDS + Amazon EC2 + ロジカルレプリケーションを使った低コスト高速全文検索」)を再演させていただきました。

これは、既存の技術を組み合わせて、なるべく楽に高速、高機能な全文検索ができる仕組みを紹介したものです。

当日使用した資料は、以下に公開しています。
PostgreSQL Conference Japan 2019 の資料とほぼ同じですが、 PostgreSQL Conference Japan 2019 で頂いた質問を元に一部加筆しています。

関連リンク:

内容

内容については、PostgreSQL Conference Japan 2019 の再演となりますので、PostgreSQL Conference Japan 2019:Amazon RDS + Amazon EC2 + ロジカルレプリケーションを使った低コスト高速全文検索 #pgcon19jの内容とほぼ同じです。

ただ、PostgreSQL Conference Japan 2019 にて、この構成は同期レプリケーションと非同期レプリケーションのどちらを使っているのか?という質問をいただいていたので、この質問についての回答を追記しています。(スライドの85 - 90ページが追記した内容です。)

以下に追記した内容について記載します。

同期、非同期どちらのレプリケーションでもAmazon RDS + Amazon EC2 + ロジカルレプリケーション + PGroongaを使った低コスト高速全文検索の構成を使うことができます。

ただ、同期、非同期のレプリケーションを使った構成にはそれぞれ以下の特徴があるので、これらの特徴を踏まえた上でユースケースに合わせて選択することをおすすめします。

  • 同期レプリケーション
    • 同期レプリケーションでは、Subscriberの更新を待ってから応答を返すため、非同期レプリケーションに比べて更新性能は落ちてしまう。
    • Subscriberの更新を待つので、PublisherとSubscriberのデータは同一であることが保証される。
  • 非同期レプリケーション
    • 非同期レプリケーションでは、Subscriberの更新を待たずに応答を返すため、同期レプリケーションに比べて更新性能は高い。
    • Subscriberの更新を待たないので、PublisherとSubscriberのデータが同一でないことがある。(タイミングによっては、更新前のデータが見えてしまう。)

同期レプリケーションでは、PublisherとSubscriberのデータが同一であることが保証されるので、更新したデータを即時検索できることがとても重要な場合は、同期レプリケーションを選択することをおすすめします。

そうではない場合は、非同期レプリケーションを選択して更新性能を落とさず検索できるようにすることをおすすめします。

まとめ

今回の発表にあたって、追記した内容を中心に紹介いたしました。
中国地方DB勉強会の皆様、中国地方のコミュニティでの発表という貴重な機会をいただきありがとうございました。

最後に、PGroongaを使った全文検索について、興味、疑問などございましたら、是非、お問い合わせください。

タグ: Groonga
2020-01-28

«前月 最新記事 翌月»
タグ:
年・日ごとに見る
2008|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|06|07|08|09|10|11|12|
2011|01|02|03|04|05|06|07|08|09|10|11|12|
2012|01|02|03|04|05|06|07|08|09|10|11|12|
2013|01|02|03|04|05|06|07|08|09|10|11|12|
2014|01|02|03|04|05|06|07|08|09|10|11|12|
2015|01|02|03|04|05|06|07|08|09|10|11|12|
2016|01|02|03|04|05|06|07|08|09|10|11|12|
2017|01|02|03|04|05|06|07|08|09|10|11|12|
2018|01|02|03|04|05|06|07|08|09|10|11|12|
2019|01|02|03|04|05|06|07|08|09|10|11|12|
2020|01|02|03|04|05|06|07|08|