flywayのmultiple databases migration の設定メモ

flyway でdb migrateしているが、公式ドキュメントではmultiple schemaは記述の仕方でなんとかなるんだけど、DBが分かれた場合は、地道にタスクを書くしかないっぽくて、そんなの嫌なのでちょっとメモ。

全体構成

一旦こんな感じのディレクトリ構成にしてみる。

├── build.gradle
├── conf
│   ├── example-admin.conf
│   └── example.conf
└── src
    └── main
        └── resources
            ├── example
            │   └── migration
            │       ├── V201801060359__create_account_table.sql
            │       └── V201801070137__create_table.sql
            └── example-admin
                └── migration
                    ├── V201801060359__create_account_table.sql
                    └── V201801070137__create_table.sql

resourcesディレクトリ

SQLはsrc/main/resources配下にexampleとexample-adminの配下にマイグレーション用のSQLファイルがおいてある。

build.gradle

汚いけど、taskを動的生成する

build.gradle

repositories {
    jcenter()
}

dependencies {
    compile 'org.slf4j:slf4j-api:1.7.24'
    testCompile 'junit:junit:4.12'
}

["example", "example-admin"].each { name ->
    task  "${name}FlywayMigrate" (type: org.flywaydb.gradle.task.FlywayMigrateTask) {
        configFiles = ["conf/${name}.conf"]
    }

    task "${name}FlywayBaseline"(type: org.flywaydb.gradle.task.FlywayBaselineTask) {
        configFiles = ["conf/${name}.conf"]
    }

    task  "${name}FlywayClean"(type: org.flywaydb.gradle.task.FlywayCleanTask) {
        configFiles = ["conf/${name}.conf"]
    }

    task  "${name}FlywayInfo"(type: org.flywaydb.gradle.task.FlywayInfoTask) {
        configFiles = ["conf/${name}.conf"]
    }
}

こんな感じで、タスクを動的生成するようにする

confディレクトリ

ここにはDBとスキーマの定義ファイルがおいてある
confファイルはこんな感じ

conf/example.conf

flyway.url=jdbc:postgresql://localhost:5432/example
flyway.user=example
flyway.password=example
flyway.schemas=public
flyway.locations=filesystem:src/main/resources/example/migration

conf/example-admin.conf

flyway.url=jdbc:postgresql://localhost:5432/example-admin
flyway.user=exampleadmin
flyway.password=exampleadmin
flyway.schemas=public
flyway.locations=filesystem:src/main/resources/example-admin/migration

家族全員をMVNO(IIJ)にした話

昨年の年末までに家族の通信費の棚卸しをしました。

ざっくり、その過程を紹介しようかと。

MVNOにする前の状況はこんなかんじです。料金とかはざっくりなのです。許してください。

キャリア ざっくり料金 備考
自分 ソフトバンク 2500円
自分 UQ-mobile 4200円 モバイルルータ
奥さん ソフトバンク 7500円
父親(自分) ソフトバンク 2500円 ガラケー
母親(自分) ソフトバンク 2500円 ガラケー
父親(奥さん) 持ってない
母親(奥さん) softbank(ガラケー) 4000円 ガラケー

計 23200円/月

両方の父親・母親に関しては結構SMSだったり通話を多用していた。

自分が乗り換えてみる

2016年1月
IIJにさっそく乗り換えてみる。
通話あり+データ6GBのIIJのプランにした。
1年運用してほとんど問題ないので、布教活動を行うことにする。
6GBあれば、デザリングとかも十分できるので、イケると判断
2560円

母親にデータSIMを入れたスマホを渡す

2016年10月
自分の両親ともにガラケーだったので、データSIMを入れたスマホを渡すことにした。
必要な連絡はチャット等したり、地図は便利だよーとかいう布教活動を行う
母親はスマホに興味があったので、最初は大変だったが、使えるように。
孫の写真とかも送ったら、喜んでくれた。ガラケだと、データ通信料が固定じゃないことが多いので、なかなかできなかった。
900円

妻の実家にスマホを持ってもらう

2017年5月
北朝鮮問題や地震などの災害等の対策として、スマホにしてくださいとお願いする。
東日本大震災でも、電話のような同期的なツールはほとんどつながらないけど、チャットやツイッター等は非同期ツールは繋がりさえすれば
テキストで書いたものが見られるので、絶対連絡とりたいから持っておいてくださいとお願いして持ってもらうことに。
最初はなれないスマホでリモートでヘルプの対応するのはなかなか大変だったが、今では普通に使ってもらえてる。

IIJ通話 + データ3GB + 通話10分し放題のプランにする
1600円 + 860円

自分の実家の母親をスマホに

2017年10月

実家の母親のガラケの更新月がきたので、スマホに切り替えてもらう。
MNP番号をもらうのに、結構売り込みをされたみたいだが、なんとか移行完了

IIJ通話 + データ3GB + 通話10分し放題のプランにする
1600円 + 860円

父親にガラスマホを渡す(データのみ)

2017年10月
ガラケ大好きな親に、ガラケは近い将来2020年以降には停波しちゃうかもしれないから、今のうちからやっておきましょうとお願いをして、ガラホだったら持ってもいいということで、もつことに。しかし、渡したのはいいけど、かなり使いにくく、失敗したとおもっている。

IIJデータ3GB
900円

妻のSIMをMVNOに

最後の最後で、妻のSIMをMVNOに切り替える。
iPhone6だったので、端末も新しくする。(これが一番お金がかかった)

IIJ通話 + データ3GB + 通話10分し放題のプランにする
1600円 + 860円

切り替えおわって

双方の両親のガラケからスマホに切り替えるオペレーション的な問題以外は問題はひとつも発生しなかったです。
IIJさんが安定したインフラを運用してくださってるからですね。

総額年15万も安くなって、docomo回線にもなって大変快適になりました。(ソフトバンクは変なところでつながらないとかよくあった)
ともあれ、ガラケに固執する世代には、

  • 災害時のための連絡手段
  • ガラケは2020年以降は徐々に停波になるかも

の2つでクリアできるかと思います。
また、孫の写真等送ってあげたり、アルバムアプリを入れて共有したりすると効果的かもしれません。

あと、ガラホ(ガラケーとスマホが一緒になった機種)は選ばない方がいいです。
スマホの機能は使えるけど、かなり使いづらいので。

最後に料金計算です

キャリア ざっくり料金 備考
自分 IIJMIO 2500円
奥様 IIJMIO 2460円
父親(自分) IIJMIO 900円 スマホ
母親(自分) IIJMIO 2460円 スマホ
父親(奥様方) IIJMIO 1600 スマホ
母親(奥様方) IIJMIO 2460円 スマホ

12400円/月

となりまして、年12万くらいの節約になります。
1人はスマホもっていなかったのに、もった状態でこれくらいの金額になります。
ぜひ、両親等もスマホに切り替えてあげてください。

いつでも、お安いのでぜひどうぞ。

Java8で追加された関数型のメモ(いまさら)

今更だけど、Java8の関数型インターフェースのメモ

Consumer

引数1つ受け取って、結果を返却しない関数インターフェース

public class ConsumerSample<T> {

    public static void main(String[] args) {
        Consumer<String> consumer1 = string -> System.out.println("consumer1: " + string);
        consumer1.accept("sample");

        Consumer<String> consumer2 = string -> System.out.println("consumer2: " + string);
        Consumer<String> sumConsumer = consumer1.andThen(consumer2);
        sumConsumer.accept("Hello Consumer!");
    }
}

accept(T t)

引数で設定されたオペレーションを実行する

andThen(Consumer<? super T> after)

Consumerをつなげて、合成Consumerを返却する

Supplier

public class SupplierSample {
    public static void main(String[] args) {

        Supplier<String> supplier = () -> "hoge";
        System.out.println(supplier.get());
    }
}

get()

ジェネリクスで指定した型が結果として返却される

Predicate

真偽値を返却する関数インターフェース

public class PredicateSample {
    public static void main(String[] args) {

        // test
        Predicate<String> predicate = string -> string.isEmpty();
        System.out.println(predicate.test(""));
        System.out.println(predicate.test("test"));

        // nagate  (結果はtestの反対になる)
        Predicate<String> predicateNegate = predicate.negate();
        System.out.println(predicateNegate.test(""));
        System.out.println(predicateNegate.test("test"));

        // and
        Predicate<String> predicateContains = string -> string.contains("c");
        Predicate<String> predicateStart = string -> string.startsWith("a");
        Predicate<String> and = predicateContains.and(predicateStart);
        System.out.println(and.test("cab"));
        System.out.println(and.test("abc"));

    }
}

test(T t)

設定したPredicateを検証する

nagate()

Predicateの否定したインスタンスを返却する

and(Predicate<? super T>)

設定したPredicateを合成する

BiConsumer,BiSupplier,BiPredicate

上3つの引数2つ版

ホワイトボードシートを買ったら捗った話

タイトルどおりですけど、ホワイトボードシートを買ったらとっても捗った話。
ホワイトボードってやっぱり神だわとおもいました。

買ったシートはこちら↓

ホワイトボードシートの良さとしては
– パッとかけて、さっと消せる(消したあとも結構きれい)
– サイズが複数ある
– 子供のお絵かきに最適
– 平らなところなら、どこでも張れる
– スペース取らない
– マグネットが使える(磁力はそれほど強くないけど)
– camiappというアプリが優秀
– 傾き検知とかしてくれる
– 画質も良好

これまではもっと薄手の静電気で貼り付けるシートを使ってましたけど、マグネットが使いたくでさがしたらありました。
価格は少々6000円と少しかかりますが、どこにでも貼れるので便利です。

壁紙に凹凸がある場合は、3Mのコマンドタブを使うと、剥がした時にも壁紙がきれいです。

興味があったらぜひお試しを。

Springのアノテーション(@Async)で非同期を使う

Springで非同期処理を簡単に使う方法のメモ

参考はこちら -> Spring MVC(+Spring Boot)上での非同期リクエストを理解する

Springデフォルトの非同期

Springは起動クラスにアノテーションをつけるだけで、非同期処理ができる

@EnableAsyncを起動クラスに追加する

Application.java

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;

@SpringBootApplication
@EnableAutoConfiguration
@EnableAsync // <- これ追加する
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class,args);
    }

}

これだけで、非同期のアノテーション(@Async)が使えるようになります。

@Asyncをつけたテキトーなクラスを作ってみます
SampleService.java

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

@Service
@Slf4j
@Async
public class TopServiceImpl {

    public String index() {

        try {
            for (int i = 0; i < 1000; i++) {
                Thread.sleep(10);
                log.info("{}",i);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return null;
    }
}

下記のようにログがでてきました

2018-01-08 23:35:24.508  INFO 20519 --- [cTaskExecutor-1] com.tasktalk.service.TopServiceImpl      : 0

cTaskExecutor-1がでてきて、呼び出し回数ごとにこのスレッドが増えていきます。
これだけだと、スレッド数を管理できません。

スレッド数をSpringで管理する

WebMvcConfigurerAdapterを継承したクラスでメソッド2つ追加する

WebMvcConfig.java

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.AsyncTaskExecutor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.web.servlet.config.annotation.AsyncSupportConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

@Configuration
@ComponentScan
public class WebMvcConfig extends WebMvcConfigurerAdapter {

    @Override
    public void configureAsyncSupport(AsyncSupportConfigurer configurer) {  // <- このメソッド追加
        configurer.setTaskExecutor(taskExecutor());
    }

    @Bean
    public AsyncTaskExecutor taskExecutor(){ // <- このメソッド追加
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); 
        executor.setCorePoolSize(10);
        executor.setMaxPoolSize(10);
        executor.setQueueCapacity(10);
        return executor;
    }
}

下記のようにログがでてきました

2018-01-08 23:30:53.612  INFO 20519 --- [ taskExecutor-1] com.tasktalk.service.TopServiceImpl      : 149

taskExecutor-1と表記されていて、設定したスレッドプールから使用されております。

PostgreSQLの予約語

PostgreSQLの予約語って結構多いと思うけど、リンクメモ

https://www.postgresql.jp/document/9.6/html/sql-keywords-appendix.html

userテーブルとかつくれなかった。。。予約語にあるから。

gradleの記述仕方メモ

gradleはmavenと異なってxmlではなく、DSLやgroovyで記述できるけど、記述する順番とかあるので、メモ

buildscript

これはほとんどファイルの先頭にあること

plugins

pluginsブロックを使うなら、ファイルの先頭かbuildscriptブロックの次にあること

./gradlewのアップグレード

./gradlewの中身をアップデートしたい。。。のでメモ

./gradlew --version

------------------------------------------------------------
Gradle 4.0.1
------------------------------------------------------------

Build time:   2017-07-07 14:02:41 UTC
Revision:     38e5dc0f772daecca1d2681885d3d85414eb6826

Groovy:       2.4.11
Ant:          Apache Ant(TM) version 1.9.6 compiled on June 29 2015
JVM:          1.8.0_25 (Oracle Corporation 25.25-b02)
OS:           Mac OS X 10.13.2 x86_64

こんな感じになる。
gradle-wrapper.propertiesを書き換える

$ vi gradle/wrapper/gradle-wrapper.properties

- distributionUrl=https\://services.gradle.org/distributions/gradle-4.0.1-bin.zip
+ distributionUrl=https\://services.gradle.org/distributions/gradle-4.4.1-bin.zip

書き換えたらコマンドを叩く

$ ./gradlew wrapper

バージョンを確認する

$ ./gradlew --version

------------------------------------------------------------
Gradle 4.4.1
------------------------------------------------------------

Build time:   2017-12-20 15:45:23 UTC
Revision:     10ed9dc355dc39f6307cc98fbd8cea314bdd381c

Groovy:       2.4.12
Ant:          Apache Ant(TM) version 1.9.9 compiled on February 2 2017
JVM:          1.8.0_25 (Oracle Corporation 25.25-b02)
OS:           Mac OS X 10.13.2 x86_64

以上!