個人的な備忘録
IDのクラスに対してGenericsを使った共通の関数を持たせたいなーというのがあって、
reflection使えばとりあえず出来そうだったのでこれを仕事で使ってみている
ただなんかcompanion object側のクラスに対してinterface継承させずにやる方法もあるんじゃないかと思って若干もやっている
(調べて見た感じぱっと見当たらなかった)
KotlinでmockStaticを使おうとしてちょっとハマった話
kotlin
書いてて、mockito-inline
の mockStatic
を使おうとして
少し時間無駄にしたので、他の人が同じことで時間を無駄にしないように書いとく
tl;dr
@JvmStatic
のAnnotationをつける必要がある
普通に考えれば当たり前なんだけど、つけ忘れてた時にエラー出てなんでだっけ?ってなる
object ExampleObject { @JvmStatic //これ fun static(): String { return "static" } }
なぜか
じゃないとバイトコードになった時に static
にならないので結果としてmock出来ずに失敗する
// ================com/example/springkotlin/utils/ExampleObject.class ================= // class version 52.0 (52) // access flags 0x31 public final class com/example/springkotlin/utils/ExampleObject { // access flags 0x19 public final static static()Ljava/lang/String; @Lkotlin/jvm/JvmStatic;() @Lorg/jetbrains/annotations/NotNull;() // invisible L0 LINENUMBER 6 L0 LDC "static" ARETURN L1 MAXSTACK = 1 MAXLOCALS = 0 // access flags 0x11 public final notStatic()Ljava/lang/String; @Lorg/jetbrains/annotations/NotNull;() // invisible L0 LINENUMBER 10 L0 LDC "notStatic" ARETURN L1 LOCALVARIABLE this Lcom/example/springkotlin/utils/ExampleObject; L0 L1 0 MAXSTACK = 1 MAXLOCALS = 1 // access flags 0x2 private <init>()V L0 LINENUMBER 3 L0 ALOAD 0 INVOKESPECIAL java/lang/Object.<init> ()V RETURN L1 LOCALVARIABLE this Lcom/example/springkotlin/utils/ExampleObject; L0 L1 0 MAXSTACK = 1 MAXLOCALS = 1 // access flags 0x19 public final static Lcom/example/springkotlin/utils/ExampleObject; INSTANCE @Lorg/jetbrains/annotations/NotNull;() // invisible // access flags 0x8 static <clinit>()V L0 LINENUMBER 3 L0 NEW com/example/springkotlin/utils/ExampleObject DUP INVOKESPECIAL com/example/springkotlin/utils/ExampleObject.<init> ()V ASTORE 0 ALOAD 0 PUTSTATIC com/example/springkotlin/utils/ExampleObject.INSTANCE : Lcom/example/springkotlin/utils/ExampleObject; RETURN MAXSTACK = 2 MAXLOCALS = 1 @Lkotlin/Metadata;(mv={1, 6, 0}, k=1, d1={"\u0000\u0014\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0002\u0008\u0002\n\u0002\u0010\u000e\n\u0002\u0008\u0002\u0008\u00c6\u0002\u0018\u00002\u00020\u0001B\u0007\u0008\u0002\u00a2\u0006\u0002\u0010\u0002J\u0006\u0010\u0003\u001a\u00020\u0004J\u0008\u0010\u0005\u001a\u00020\u0004H\u0007\u00a8\u0006\u0006"}, d2={"Lcom/example/springkotlin/utils/ExampleObject;", "", "()V", "notStatic", "", "static", "spring-kotlin"}) // compiled from: ExampleObject.kt }
エラー
エラーとしてはこんなのが出るけどぱっと見ですぐに気がつきにくい
when() requires an argument which has to be 'a method call on a mock'. For example: when(mock.getArticles()).thenReturn(articles); Also, this error might show up because: 1. you stub either of: final/private/equals()/hashCode() methods. Those methods *cannot* be stubbed/verified. Mocking methods declared on non-public parent classes is not supported. 2. inside when() you don't call method on mock but on some other object. org.mockito.exceptions.misusing.MissingMethodInvocationException: when() requires an argument which has to be 'a method call on a mock'. For example: when(mock.getArticles()).thenReturn(articles); Also, this error might show up because: 1. you stub either of: final/private/equals()/hashCode() methods. Those methods *cannot* be stubbed/verified. Mocking methods declared on non-public parent classes is not supported. 2. inside when() you don't call method on mock but on some other object.
コード
package com.example.springkotlin.utils object ExampleObject { @JvmStatic fun static(): String { return "static" } fun notStatic(): String { return "notStatic" } }
テスト
package com.example.springkotlin.utils import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test import org.mockito.Mockito.mockStatic class ExampleObjectTest { @Test fun test() { // 雑 val mocked = mockStatic(ExampleObject::class.java) mocked.`when`<String>(ExampleObject::static).thenReturn("mocked") assertEquals("mocked", ExampleObject.static()) mocked.close() } }
Atlantisのカスタムワークフローで実行されるTerraformのバージョンが指定と異なる
issueにもなってた
なんか見栄えが悪いけど現状こうするしかないっぽい
version: 3 projects: - name: test dir: projects/test terraform_version: 1.1.6 #明示的に指定したい workflows: default: plan: steps: - init # これはterraform_versionで実行される - plan # これはdefaultのterraform versionで実行される - run: terraform plan -input=false -refresh -no-color -out $PLANFILE # 明示的に指定することでterraform_versionで実行される - run: terraform$ATLANTIS_TERRAFORM_VERSION plan -input=false -refresh -no-color -out $PLANFILE ...
Terraform detected the following changes made outside of Terraformを無視することにした
実質メモ書き
尚、未だに公式的に回避する手立てがあるわけではないので、そこは実装されるのを待つしかない。
Terraform
の 0.15.4
以降、これが出てくるようになった。
現状 ignore_changes
するぐらいしかろくな回避手段がないが、ignore_changes
は別にその為に使うもんでもないので悩んでいた。
(IAMとかのPolicyの変更ノイズが個人的にとてもつらいし、長いログが出力されてしまうのがきつい)
それでまあ Issue を眺めてたら言及されている Issue を見つけた。
荒れに荒れて10月にはIssue自体がロックされてしまったらしい。
(追記) 1.2でなんか対応入ったっぽい
個人的にはリフレッシュに対する差分が長すぎて、
変更差分を見落とすほうがつらいのでIssueのコメントにかかれているように、sed
で無視することにした。
lockされているとコメントにスタンプ押せないのでこの場で感謝。
早くリソースの Attribute レベルで更新差分を無視することが出来るようになってほしい。
terraform plan | grep -v "Refreshing state..." | sed '/Objects have changed outside of Terraform/,/────────────/d'
auroraでフェイルオーバーした際にコネクションの接続がぜんぜん切り替わらなくて色々見てたのでメモ
環境
Aurora postgresql
Spring Boot
- driver は
org.postgresql.driver
- driver は
Doma
メモ
AWSのベストプラクティスにも書かれているやつで、targetServerType
を primary
に指定しておけばFOした際に自動的にコネクションが再接続される
jdbc:postgresql://myauroracluster.cluster-c9bfei4hjlrd.us-east-1-beta.rds.amazonaws.com:5432,myauroracluster.cluster-ro-c9bfei4hjlrd.us-east-1-beta.rds.amazonaws.com:5432/postgres?user=<primaryuser>&password=<primarypw>&loginTimeout=2&connectTimeout=2&cancelSignalTimeout=2&socketTimeout=60&tcpKeepAlive=true&targetServerType=primary
targetServerType = String
Allows opening connections to only servers with required state, the allowed values are any, primary, master, slave, secondary, preferSlave and preferSecondary. The primary/secondary distinction is currently done by observing if the server allows writes. The value preferSecondary tries to connect to secondary if any are available, otherwise allows falls back to connecting also to primary. jdbc.postgresql.org
ただAWS公式だと参照系クエリをreplicaに逃がす部分の話はなかったので、一応pgjdbcの実装を確認した github.com
HostStatus hostStatus = HostStatus.ConnectOK; if (candidateHost.targetServerType != HostRequirement.any) { hostStatus = isPrimary(queryExecutor) ? HostStatus.Primary : HostStatus.Secondary; } GlobalHostStatusTracker.reportHostStatus(hostSpec, hostStatus); knownStates.put(hostSpec, hostStatus); if (!candidateHost.targetServerType.allowConnectingTo(hostStatus)) { queryExecutor.close(); continue; }
Tuple results = SetupQueryRunner.run(queryExecutor, "show transaction_read_only", true);
で接続先がreadonlyかどうかチェックしているらしい
primary { public boolean allowConnectingTo(@Nullable HostStatus status) { return status == HostStatus.Primary || status == HostStatus.ConnectOK; } }, secondary { public boolean allowConnectingTo(@Nullable HostStatus status) { return status == HostStatus.Secondary || status == HostStatus.ConnectOK; } },
allowConnectingTo
でコネクションが接続先の条件(targetServerType
で指定した HostStatus
)にマッチしているかを確かめて、マッチしていなければクローズするみたいな実装にしているらしい
pgjdbc/HostRequirement.java at a966396c5e2ac3398ba5196d5e9baed705cf593e · pgjdbc/pgjdbc · GitHub
最終的に
書き込み用のコネクションプールの接続をjdbc:postgresql://<cluster_endpoiont>?targetServerType=primary
参照用のコネクションプールの接続をjdbc:postgresql://<cluster_readonly_endpoint>?targetServerType=secondary
にしていい感じになった
他にもベストプラクティスのパラメータ足したり、SpringBoot使ってるのでHikariCP周りの設定した