PostgreSQL のトリガーは同期か非同期か?

まー普通に考えたらトランザクション維持できないから同期じゃないとダメだし。

CREATE FUNCTION wait() RETURNS TRIGGER AS $$
    BEGIN
        PERFORM pg_sleep(10);
        RETURN NEW;
    END;
$$ LANGUAGE plpgsql;

CREATE TABLE foo ( id serial primary key, name varchar(100));

CREATE TRIGGER trigger_foo
    BEFORE INSERT OR UPDATE ON foo
    FOR EACH ROW
    EXECUTE PROCEDURE wait();

INSERT INTO foo(name) VALUES ('foobar');

macport で distfile がダウンロードできないとき

macport を認証 Proxy 環境で使用しているとまれに、Proxy の所為でパッケージの distfile がダウンロードできない事象が発生する。

例えば boost の場合

--->  Fetching distfiles for boost
--->  Attempting to fetch boost_1_59_0.tar.bz2 from http://freefr.dl.sourceforge.net/project/boost/boost/1.59.0
--->  Attempting to fetch boost_1_59_0.tar.bz2 from http://heanet.dl.sourceforge.net/project/boost/boost/1.59.0
--->  Attempting to fetch boost_1_59_0.tar.bz2 from http://internode.dl.sourceforge.net/project/boost/boost/1.59.0
--->  Attempting to fetch boost_1_59_0.tar.bz2 from http://iweb.dl.sourceforge.net/project/boost/boost/1.59.0
--->  Attempting to fetch boost_1_59_0.tar.bz2 from http://jaist.dl.sourceforge.net/project/boost/boost/1.59.0
--->  Attempting to fetch boost_1_59_0.tar.bz2 from http://kent.dl.sourceforge.net/project/boost/boost/1.59.0
--->  Attempting to fetch boost_1_59_0.tar.bz2 from http://liquidtelecom.dl.sourceforge.net/project/boost/boost/1.59.0
--->  Attempting to fetch boost_1_59_0.tar.bz2 from http://nbtelecom.dl.sourceforge.net/project/boost/boost/1.59.0
--->  Attempting to fetch boost_1_59_0.tar.bz2 from http://nchc.dl.sourceforge.net/project/boost/boost/1.59.0
--->  Attempting to fetch boost_1_59_0.tar.bz2 from http://ncu.dl.sourceforge.net/project/boost/boost/1.59.0
--->  Attempting to fetch boost_1_59_0.tar.bz2 from http://netassist.dl.sourceforge.net/project/boost/boost/1.59.0
--->  Attempting to fetch boost_1_59_0.tar.bz2 from http://netcologne.dl.sourceforge.net/project/boost/boost/1.59.0
--->  Attempting to fetch boost_1_59_0.tar.bz2 from http://netix.dl.sourceforge.net/project/boost/boost/1.59.0
--->  Attempting to fetch boost_1_59_0.tar.bz2 from http://skylineservers.dl.sourceforge.net/project/boost/boost/1.59.0
--->  Attempting to fetch boost_1_59_0.tar.bz2 from http://skylink.dl.sourceforge.net/project/boost/boost/1.59.0
--->  Attempting to fetch boost_1_59_0.tar.bz2 from http://superb-dca2.dl.sourceforge.net/project/boost/boost/1.59.0
--->  Attempting to fetch boost_1_59_0.tar.bz2 from http://tcpdiag.dl.sourceforge.net/project/boost/boost/1.59.0
--->  Attempting to fetch boost_1_59_0.tar.bz2 from http://tenet.dl.sourceforge.net/project/boost/boost/1.59.0
--->  Attempting to fetch boost_1_59_0.tar.bz2 from http://ufpr.dl.sourceforge.net/project/boost/boost/1.59.0
--->  Attempting to fetch boost_1_59_0.tar.bz2 from http://vorboss.dl.sourceforge.net/project/boost/boost/1.59.0
--->  Attempting to fetch boost_1_59_0.tar.bz2 from https://distfiles.macports.org/boost
--->  Attempting to fetch boost_1_59_0.tar.bz2 from http://aarnet.au.distfiles.macports.org/pub/macports/mpdistfiles/boost
--->  Attempting to fetch boost_1_59_0.tar.bz2 from http://cjj.kr.distfiles.macports.org/boost
--->  Attempting to fetch boost_1_59_0.tar.bz2 from http://fco.it.distfiles.macports.org/mirrors/macports-distfiles/boost
--->  Attempting to fetch boost_1_59_0.tar.bz2 from http://her.gr.distfiles.macports.org/boost
--->  Attempting to fetch boost_1_59_0.tar.bz2 from http://jnb.za.distfiles.macports.org/distfiles/boost
--->  Attempting to fetch boost_1_59_0.tar.bz2 from http://jog.id.distfiles.macports.org/macports/distfiles/boost
--->  Attempting to fetch boost_1_59_0.tar.bz2 from http://lil.fr.distfiles.macports.org/boost
--->  Attempting to fetch boost_1_59_0.tar.bz2 from http://mse.uk.distfiles.macports.org/sites/distfiles.macports.org/boost
--->  Attempting to fetch boost_1_59_0.tar.bz2 from http://nou.nc.distfiles.macports.org/pub/macports/distfiles.macports.org/boost
--->  Attempting to fetch boost_1_59_0.tar.bz2 from http://nue.de.distfiles.macports.org/boost
--->  Attempting to fetch boost_1_59_0.tar.bz2 from http://osl.no.distfiles.macports.org/boost
--->  Attempting to fetch boost_1_59_0.tar.bz2 from http://sea.us.distfiles.macports.org/macports/distfiles/boost
--->  Attempting to fetch boost_1_59_0.tar.bz2 from http://ykf.ca.distfiles.macports.org/MacPorts/mpdistfiles/boost
--->  Attempting to fetch boost_1_59_0.tar.bz2 from http://svn.macports.org/repository/macports/distfiles/boost
Error: org.macports.fetch for port boost returned: fetch failed
Error: Failed to install boost

特定のパッケージだけではない場合はネットワークとか Proxy 設定とかを疑うのが正しいのだが、特定のパッケージだけで発生する場合、一体なにが原因なのかがよくわからない事が多い(大抵 Proxy 側の問題の方が多い気がする)。

そんな場合は、取得できない distfile をブラウザで取得し、/opt/local/var/macports/distfiles/ 以下に配置してあげればすんなりインストールできる。

boost の場合は以下に配置

/opt/local/var/macports/distfiles/boost

その後は普通に

$sudo port install boost

楽天

corp.rakuten.co.jp

楽天のトップページが更新されたそうです。そこで最近のWebはどのくらいで表示できるものか計測してみました。 パソコン(MacBookAir 2.13 GHz Intel Core 2 Duo、メモリ4G )やブラウザ(Firefox 40.0.2)、ネットワーク(Wimax)のスペックによって変わるとは思いますが、計測環境はそんなに悪くないと思います。

Firefox のアドオン FireBug で計測した結果です。感想です。

  • HTML のレスポンスは早いけど、表示までは凄い時間がかかる。
  • 大量( 500 以上)のリクエストを発行している。
  • データサイズもそれに比例して多い。
  • 広告系のリクエスト多い(これちょっと違うかもしれません。Adblockの所為かも)。
  • やたら Cookie 発行されている。
  • ブラウザのキャッシュありきな感じで設計されている。

一言で言えば「重い(と思った)」です。こんなモンなのかなぁ?

キャッシュなし

f:id:izuno4t:20150823230203p:plain

キャッシュあり

f:id:izuno4t:20150823230206p:plain

db:migrate

SkinnyFramework で db:migration するとエラーになっちゃった。

DB Migration - Skinny Framework の Try now を PostgreSQL に変更してやってみたらエラーになる。Flyway で使ってるメタデータの schema_version ができてないと。

Flyway の task の中には Baseline をつくるコマンドがあるんだけど。Skinny の task には migrate と repair しかないので、baseline をつくるための指定する手段がなさそう。

h2 のデータベースでやると成功するだよね。こりゃ最初からつまずいた。

2015-05-31 17:47:31.947 DEBUG   --- [     run-main-0] scalikejdbc.ConnectionPool$              : Registered connection pool : ConnectionPool(url:jdbc:postgresql://localhost:5432/sandbox?loginTimeout=3&socketTimeout=10, user:sandbox) using factory : commons-dbcp2
2015-05-31 17:47:31.985  INFO   --- [     run-main-0] o.f.core.internal.util.VersionPrinter    : Flyway 3.2.1 by Boxfuse
2015-05-31 17:47:32.338  INFO   --- [     run-main-0] o.f.c.i.dbsupport.DbSupportFactory       : Database: jdbc:postgresql://localhost:5432/sandbox?loginTimeout=3&socketTimeout=10 (PostgreSQL 9.3)
2015-05-31 17:47:32.443  INFO   --- [     run-main-0] o.f.core.internal.command.DbValidate     : Validated 1 migration (execution time 00:00.059s)
[error] (run-main-0) org.flywaydb.core.api.FlywayException: Found non-empty schema "public" without metadata table! Use baseline() or set baselineOnMigrate to true to initialize the metadata table.
org.flywaydb.core.api.FlywayException: Found non-empty schema "public" without metadata table! Use baseline() or set baselineOnMigrate to true to initialize the metadata table.
    at org.flywaydb.core.Flyway$1.execute(Flyway.java:1035)
    at org.flywaydb.core.Flyway$1.execute(Flyway.java:1006)
    at org.flywaydb.core.Flyway.execute(Flyway.java:1418)
    at org.flywaydb.core.Flyway.migrate(Flyway.java:1006)
    at skinny.dbmigration.DBMigration$class.migrate(DBMigration.scala:39)
    at skinny.dbmigration.DBMigration$.migrate(DBMigration.scala:11)
    at skinny.task.DefaultTaskLauncher$$anonfun$18.apply(DefaultTaskLauncher.scala:36)
    at skinny.task.DefaultTaskLauncher$$anonfun$18.apply(DefaultTaskLauncher.scala:34)
    at skinny.task.SkinnyTaskLauncher$$anonfun$main$2.apply(SkinnyTaskLauncher.scala:25)
    at skinny.task.SkinnyTaskLauncher$$anonfun$main$2.apply(SkinnyTaskLauncher.scala:25)
    at scala.Option.map(Option.scala:146)
    at skinny.task.SkinnyTaskLauncher$class.main(SkinnyTaskLauncher.scala:25)
    at TaskRunner$.main(TaskRunner.scala:1)
    at TaskRunner.main(TaskRunner.scala)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:483)
[trace] Stack trace suppressed: run last task/compile:run for the full output.
java.lang.RuntimeException: Nonzero exit code: 1
    at scala.sys.package$.error(package.scala:27)
[trace] Stack trace suppressed: run last task/compile:run for the full output.
[error] (task/compile:run) Nonzero exit code: 1
[error] Total time: 19 s, completed 2015/05/31 17:47:32

2015.6.8 追記

Flyway がデータベースに何らかのオブジェクトがあると schema_version を生成しないみたい。schema_version なければ生成すればいいと思うんだけど、なにか意図があるんだろうな

テキストエディタ

最近高機能なテキストエディタのブームがきているので、色々と試しています。

色んな機能がプラグインで提供されているのは良いのですが、本体の開発とプラグインとの開発が当然非同期なので、本体のバージョンアップがあるとてんやわんやです。

僕の結論としては新興のテキストエディタAtom、Brackets)はまだ日常で使うには拙速の様な気がします。SublimeText も Ver3.x はまだまだ β 版ですし。。。

で、結局テキストエディタとしては CotEditor と SublimeText2 、Vim を使ってるわけですが。。。

ということで、以下 Atom、Brackets、SublimeText3 のメモです。

  • Brackets は認証 Proxy を越えられない子
  • SublimeText3 は SublimeText2 で使えてたパッケージが結構な確立でそのまま使える
  • Atom はまだ本体の修正がガシガシ行われているので、アップデートのインパクトによってはプラグインが全滅な時も(バグも多いので困ることも多いらしい。僕そこまで使って無いのでまだ未遭遇)。

Gradle

Ruby の rake のように、タスクをスクリプトで記述する形式のビルドツール

Java には Ant、Maven、Ivy などなど数々ありますが、スクリプトを記載するタイプ(でメジャー)のものは初めてのような。

主に Javaフレームワークなどのビルドで使われているようですが、スクリプトなのでどのような言語のプロジェクトでも利用できると思います。

Maven や Ant の資産も活用できるようにしているので、移行はスムーズかと思います。 ただ、Maven や Ant は設定を定義していくタイプですが、Gradle は処理を記述していくタイプなので使う側のノウハウはほとんど役に立たないですね。

Gradle - Build Automation Evolved

Gradle - Wikipedia, the free encyclopedia

Gradle 日本語ドキュメント

thin

Rubyアプリケーションサーバーとしては最もメリットが大きいとおもうので、贔屓にしているのだが、色々と依存関係があって、稼働環境を整備するのがちょっと面倒臭い。

なんと最近は Gemfiles に記載がないと起動しないっぽい。 これは rails が悪いのか thin が悪いのかがよくわからん

flow

取りあえず CI でビルド時に実行したかったので、Linux にインストール。

$ cat /etc/redhat-release 
CentOS release 5.11 (Final)
$ wget http://flowtype.org/downloads/flow-linux64-latest.zip
$ unzip flow-linux64-latest.zip
$ sudo cp flow/flow /usr/local/bin
$ flow -version
./flow: /lib64/libc.so.6: version `GLIBC_2.7' not found (required by ./flow)
$ sudo yum list installed | grep glibc
glibc.i686                                2.5-123                      installed
glibc.x86_64                              2.5-123                      installed
glibc-common.x86_64                       2.5-123                      installed
glibc-devel.i386                          2.5-123                      installed
glibc-devel.x86_64                        2.5-123                      installed
glibc-headers.x86_64                      2.5-123                      installed

怒られた。glibc が古いから。。。残念。。。 このバージョンの CentOS だと仕方がないみたい。

JBossAS7 with JDK8

JBossDeveloper を見ると 7.1.1 はサポートしなささそう。「WildFly 使いな」って書かれてる。 7.1.2 はテストされてる的な話も。

JBoss AS7 Supported with JDK8 | JBoss Developer

WildFly は動くみたい。

WildFly 8 Final is released! · WildFly

GlassFish もだめみたい。。。

java - Glassfish server does not work with JDK 8 - Stack Overflow

当然だけど実行環境としては問題なさそう。取りあえず起動はした。 Tomcat7 がダメだったのは、単に環境の問題だったかもね。

Tomcat7 with JDK8

うごかないね。

jdk7 later になってるんだけどなぁ

Apache Tomcat - Which Version Do I Want?

java.lang.NoSuchMethodError: sun.security.ec.NamedCurve.(Ljava/lang/String;Ljava/lang/String;Ljava/security/spec/EllipticCurve;Ljava/security/spec/ECPoint;Ljava/math/BigInteger;I)V
    at sun.security.ec.CurveDB.add(CurveDB.java:147)
    at sun.security.ec.CurveDB.(CurveDB.java:171)
    at sun.security.ec.SunECEntries.putEntries(SunECEntries.java:72)
    at sun.security.ec.SunEC.(SunEC.java:76)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:408)
    at java.lang.Class.newInstance(Class.java:438)
    at sun.security.jca.ProviderConfig$2.run(ProviderConfig.java:221)
    at sun.security.jca.ProviderConfig$2.run(ProviderConfig.java:206)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.security.jca.ProviderConfig.doLoadProvider(ProviderConfig.java:206)
    at sun.security.jca.ProviderConfig.getProvider(ProviderConfig.java:187)
    at sun.security.jca.ProviderList.loadAll(ProviderList.java:282)
    at sun.security.jca.ProviderList.removeInvalid(ProviderList.java:299)
    at sun.security.jca.Providers.getFullProviderList(Providers.java:173)
    at java.security.Security.getProviders(Security.java:452)
    at org.apache.catalina.core.JreMemoryLeakPreventionListener.lifecycleEvent(JreMemoryLeakPreventionListener.java:407)
    at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:117)
    at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:90)
    at org.apache.catalina.util.LifecycleBase.setStateInternal(LifecycleBase.java:402)
    at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:99)
    at org.apache.catalina.startup.Catalina.load(Catalina.java:638)
    at org.apache.catalina.startup.Catalina.load(Catalina.java:663)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:483)
    at org.apache.catalina.startup.Bootstrap.load(Bootstrap.java:281)
    at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:455)

追記 12/26

Tomcat8 With JDK8 は問題なく動作しました。めでたし、めでたし。

MySQL5.6 のトランザクション分離レベル

MySQL5.6 のトランザクション分離レベルのデフォルトが REPEATABLE-READ になっててびびった。 5.5 も同じみたい。

Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 26209
Server version: 5.6.20 MySQL Community Server (GPL)

Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> show variables like '%iso%'
    -> ;
+---------------+-----------------+
| Variable_name | Value           |
+---------------+-----------------+
| tx_isolation  | REPEATABLE-READ |
+---------------+-----------------+
1 row in set (0.00 sec)

他の RDBMS は大抵 READ-COMMITED なのに、なぜあえて REPEATABLE-READ なんだろう。 なんかありそうだけど

Redmine 2.5.1 で bundle install したら。。。

こんなこと言われた。

Use `bundle show [gemname]` to see where a bundled gem is installed.
Post-install message from capybara:
IMPORTANT! Some of the defaults have changed in Capybara 2.1. If you're experiencing failures,
please revert to the old behaviour by setting:

    Capybara.configure do |config|
      config.match = :one
      config.exact_options = true
      config.ignore_hidden_elements = true
      config.visible_text_only = true
    end

If you're migrating from Capybara 1.x, try:

    Capybara.configure do |config|
      config.match = :prefer_exact
      config.ignore_hidden_elements = false
    end

Details here: http://www.elabs.se/blog/60-introducing-capybara-2-1

Joda-Time で期間操作

commons-lang3 でもいいけど、Joda-Time も便利なので

DateTime dts = new DateTime();
DateTime dte = dts.plusDays(1).plusMillis(1);
Interval interval = new Interval(dts, dte);

// Duration
Duration duration = interval.toDuration();
System.out.println("duration(msec): " + duration.getMillis());

long days = duration.getStandardDays();
System.out.println("duration(day): " + days);

long hours = duration.getStandardHours();
System.out.println("duration(hours): " + hours);

long miutes = duration.getStandardMinutes();
System.out.println("duration(miutes): " + miutes);

long seconds = duration.getStandardSeconds();
System.out.println("duration(seconds): " + seconds);

Joda-Time で日付操作

commns-lang3 が便利だったけど Joda-Time も便利なので

// 月初を取得
DateTime dt = DateTime.now().dayOfMonth().withMinimumValue().dayOfMonth().roundFloorCopy();
System.out.println(dt);

// 月末を取得
dt = DateTime.now().dayOfMonth().withMaximumValue().dayOfMonth().roundFloorCopy();
System.out.println(dt);

// 年末を取得
dt = DateTime.now().dayOfYear().withMaximumValue().hourOfDay().withMaximumValue().minuteOfHour()
        .withMaximumValue().secondOfMinute().withMaximumValue();
System.out.println(dt);

// 今日の8時半を取得
dt = DateTime.now().dayOfMonth().roundFloorCopy().withHourOfDay(8).withMinuteOfHour(30);
System.out.println(dt);

// 今日の23時55分を取得
dt = DateTime.now().dayOfMonth().roundFloorCopy().withHourOfDay(23).withMinuteOfHour(55);
System.out.println(dt);

// 分以下を切り捨て
dt = DateTime.now().hourOfDay().roundFloorCopy();
System.out.println(dt);

// 時間以下を切り捨て
dt = DateTime.now().dayOfMonth().roundFloorCopy();
System.out.println(dt);