まらんさんのチラ裏

その日暮らしのおじさん

node-fetch で AbortSignal を使おうとすると怒られたのでその回避策メモ

環境

  • node-fetch@2.6.9
  • @types/node-fetch@2.6.2

発生したこと

node-fetch を使っていたらこんな感じで怒られてビルドできなくなってしまった。 node-fetch を 3 系にしてもいいんだけどそれだと esm が強制されちゃうので 2 系でいきたいところ。

$ tsc
src/index.ts:29:11 - error TS2322: Type 'AbortSignal' is not assignable to type 'import("/Users/malan/repos/xxx/functions/node_modules/@types/node-fetch/externals").AbortSignal'.
  Types of property 'onabort' are incompatible.
    Type '((this: AbortSignal, ev: Event) => any) | null' is not assignable to type '((this: AbortSignal, event: any) => any) | null'.
      Type '(this: AbortSignal, ev: Event) => any' is not assignable to type '(this: AbortSignal, event: any) => any'.
        The 'this' types of each signature are incompatible.
          Type 'AbortSignal' is missing the following properties from type 'AbortSignal': reason, throwIfAborted

29           signal: controller.signal as AbortSignal,
             ~~~~~~


Found 1 error in src/index.ts:29

回避策

いろいろソースを見ていたら externals.d.ts に AbortSignal が独自定義されていたのでこいつを直接引っ張ってきて使うという方法で回避。

import fetch from 'node-fetch';
import { AbortSignal } from 'node-fetch/externals';  // add this line

...

await fetch(input, {
    ...init,
    signal: controller.signal as AbortSignal,  // cast
  });

おわり

一応 github の issue にもコメント入れておいた。

github.com

Docker PostgreSQL で could not open file "pg_wal/000000010000000000000001": No such file or directory

docker で postgresql を起動させるとエラーがでて死んでしまうことがあって、これは困ったなあということで色々調べたんですけど全然それっぽい解決策がなかったんですよね。
で、仕方ないからあれこれと試して回ってみたら Docker Desktop の割と新し目の機能である VirtioFS が悪さしているっぽいことが判明。
Experimental Feature としてリリースされるずっと前からこの機能を楽しみにしていて、「やっときたぜ!」と意気揚々として有効化していたんですけどこいつがすべての元凶だったようなので仕方なく無効化しまし た。
Experimental なんだからしょうがないよね。しょぼん。

こんなログでコケてました。

postgres-1  | fixing permissions on existing directory /var/lib/postgresql/data ... ok
postgres-1  | creating subdirectories ... ok
postgres-1  | selecting dynamic shared memory implementation ... posix
postgres-1  | selecting default max_connections ... 100
postgres-1  | selecting default shared_buffers ... 128MB
postgres-1  | selecting default time zone ... Etc/UTC
postgres-1  | creating configuration files ... ok
postgres-1  | 2022-05-12 09:29:52.039 UTC [41] LOG:  could not open file "pg_wal/000000010000000000000001": No such file or directory
postgres-1  | 2022-05-12 09:29:52.039 UTC [41] FATAL:  could not open file "pg_wal/000000010000000000000001": No such file or directory
postgres-1  | child process exited with exit code 1
postgres-1  | initdb: removing contents of data directory "/var/lib/postgresql/data"
postgres-1  | running bootstrap script ... The files belonging to this database system will be owned by user "postgres".
postgres-1  | This user must also own the server process.

無効化して解決。

新しめの機能だし、同じように困ってる人もいるんじゃないかと思うので参考になれば幸いです。

今働いている会社がとてもよいので知ってほしい&エンジニア募集

2020年の8月ごろまでフリーランスと言いつつ働きたくなかったのでほとんどニートみたいな生活してたんですけど、代表の安藤さんから声をかけられて働くことになった会社がかなり良かったので過去と現在の状況を記事にしてみる。

なんて会社?

株式会社ハックルベリー 公式HP

何やってる会社?

Shopify というカナダ初のECプラットフォームのアプリを開発している会社です。
別に Shopify にこだわっているわけじゃないけど今のところは Shopify がメインという感じ。
メインのアプリは「まるっと集客」と「定期購買」です。 公開中のアプリはこのへん:

apps.shopify.com

あとECサイト構築もやってます。

使っている技術

  • TypeScript
  • React.js
  • Prisma2
  • Hasura
  • PostgreSQL
  • Firebase
  • GCP
  • Docker

入社のキッカケ

上述したとおり引きこもっていたら代表の安藤さんに声かけられてなんとなく手伝うことになりました。
安藤さんは元々僕が起業してたときのエンジェルであり、連続起業家です。
僕は会社を売却してからフリーランスとか取締役とかであちこち手伝ったりしつつ、ちょっと隙間ができたのでこれ幸いと快適な引きこもり生活をしていました。
最初は「あんまり働きたくないし、一応他にも仕事あるっちゃあるから手伝うにしてもまあ週3ぐらいで」という感じで手伝い始めたんですけど、思いの外楽しかったのでフルコミにしました。 このときたしか僕が3人目のエンジニア。フルコミとしては2人目だったはず。

実際働いてみて

最初に感じたのは心理的安全性の高さ。

Slack でのやり取りもちゃんと相手を気遣ったやりとりだし、かしこまりすぎてもいなく、しかしちゃんと言うべきことは言う。もちろん攻撃的にならない形で。
Zoom とかで会議することもあるけど、みんな人間できてるなーって感じで話しやすいです。
楽しく会話できるし、技術的なディスカッションもできるし、建設的な発言が多いというか基本全部建設的。
エンジニアの能力も高い人が揃っているので心強い。
Shopify における技術力では日本一の男もいます。かっこいいぜ。
常に最新の技術をキャッチアップしつつ、プロダクトに活かせるのか、それともスルーまたは様子を見たほうがいいか、などの話も多いです。

あとはスピード感がすごい。
スタートアップだからスピード大事ってのはもちろんそうなんだけど、それにしたってマジかってなるぐらいのスピードで事が進んでいきます。
ぼく、置いていかれないようにがんばってる。

売上もがんがん伸びてる。
キレイに右肩上がりの成長をしているのでシンプルに楽しい。
なにか実装したら面白いぐらい数字で反応がわかる感じ。

そんな感じなので働いていて嫌なことはまあない(もちろん障害とかあると辛いお気持ちになったりするけど)のでとても働きやすい。

あと自然と相手を褒める癖がついている人が多いので褒められます。心地よい。

働き方としては、

  • フルリモートで働けて、勤務時間も自由
  • 成果が出せていればOKです

そういう会社、あるにはあると思うんですが本当にこれが実現できている会社は稀有なんじゃないでしょうか。
渋谷らへんにオフィスはあった気がするけどエンジニアはほぼ行ってないです。僕も行ってない。

現在

人も増え、なんだかんだで僕が EM もやることになったので裁量が増えたかな?というのはありつつ、元から裁量ありありだったのであまり変わらないかもしれない。
とはいえメンバーの進捗やメンタルなどなど把握しないといけないのでそれなりに意図的に意識をそちらへ向けることも増えた気がする。
ちなみに現在総勢で20人ほどになっており、上述した「まるっと集客」と「定期購買」に大きく分かれています。
人が増えることによる漠然とした不安感のようなものが最初は(ちょっぴり)あったんですが、実際増えたらみんな優秀だったので無駄に不安感を抱いていただけでした。
周りに優秀な人が増えることによって自分自身も成長できるし、相談できる相手も増えるのでとても仕事がやりやすくなった点は大きいです。

あと透明性の担保は気を使いたい部分なのですが、ハックルベリーは基本的に DM はほとんど使うことがなくて余程プライベートな内容とかじゃない限りオープンチャンネルでやり取りしているので透明性も高く保てていると言えるんじゃないでしょうか。

f:id:Malan:20220212193128p:plain
slack パブリックとプライベート

相変わらずみんな仲良くて、少なくとも僕はストレスのない生活を送っています。
プロダクトを成長させる楽しさは他の会社でもなかなか味わえないレベルになっていると思うので興味ある人はこっちにきて味わって欲しい。

また、ある程度成長したことによる課題的なものも見えてきており、

  • テストが十分書けていない
    • 対応中
  • コードの複雑化
    • テストコードがある程度形になったらリファクタしたい
  • オペレーションコストの肥大化
    • 社内で使う管理画面が割としょぼいスッキリしているのでもう少し充実させたい
  • 人が足りない
    • 絶賛採用活動中!

というものがあります。
これらはきちんと時間を割いて対応していく必要がありますが、ちゃんとスケジュールを確保して対応していってます。
本当にスケジュールの調整が必要な場合はちゃんと調整できるという点も、意外と他の会社ではできないところも多いかと思うので魅力の一つかなと思っています。
経営者がエンジニアのことを信頼してくれている証であり、本当にプロダクトを大事に育てようとしている証でもあります。

なんだか会社を褒める内容ばかりになってしまったので逆に怪しいと思われるかもしれないけど、実際これといった不満がないので仕方がない。
また、不満があっても話せば結構解消しやすい会社だとも思っている。

ということで興味を持ってくれた人はエントリーしてもらえると嬉しいです。

お知らせ

まだまだ新しいアプリも開発中なので人が足りていません。
ハックルベリーはソフトウェアエンジニアを募集中です。

huckleberry-inc.com

firebase functions が一括デプロイできなかったのをなんとかした件

シンプルに firebase deploy --only functions としていたらある日突然エラーが出てデプロイできなくなった。
仕方なく、
firebase deploy --only functions:aaa,functions:bbb,functions:ccc
という感じで1度にデプロイする function の数を10個に制限して分割デプロイしていました。
が、これがめちゃくちゃ時間がかかって、デプロイに1時間ぐらい要することになってしまい、「まあそれでもデプロイできないよりは…」ということでしばらく放置していたんですけど流石につらみが増してきてちゃんと対応しようということに。

参考にした記事はこちら:

zenn.dev

#!/bin/sh
PROJECT="your project id"
CONTAINER_REGISTRY="asia.gcr.io/$PROJECT/gcf/asia-northeast1"
IMAGE_LIST=`gcloud container images list --repository=$CONTAINER_REGISTRY | awk 'NR!=1'`
for line in $IMAGE_LIST; do
  gcloud container images --project $PROJECT delete "$line/worker" --quiet & gcloud container images --project $PROJECT delete "$line/cache" --quiet &
done
wait

GCF の images をすべて削除して functions をデプロイし直すというもの。
このスクリプトを走らせてもいいし、Console から手動でポチっと削除してもいいしどちらでも。
記事中でもダウンタイムは発生しないと書かれていたのですが流石に怖いので手元で実験しつつ問題ないことを確認して本番に適用。

当初心配していたダウンタイムも発生しなければ、一部の functions に割り当てた固定IPアドレスの設定も消えることなくすんなりとすべてが解決し、いまでは1時間かかっていたデプロイが元通りの処理時間になり、10分ほどでデプロイできるようになりました。

とっても感謝です。

別プロジェクトの firebase functions を呼び出す

firebase も GCP もなんもわからん。 ってなってたんですが、とりあえずなんとかする方法がわかったので雑にメモ。

  • Project A: 呼び出される側
  • Project B: 呼び出す側

Project A 側

A に https.onCall な function testFunc を実装する。

export const testFunc = functions
  .https.onCall(async (data) => {
  functions.logger.debug('よばれたよー');
};

GCP コンソール

A の testFunc の権限に B の IAM ユーザを Cloud Functions 起動元 として追加する。

Project B 側

B から httpsCallable で A の testFunc を呼び出す。

export const callTestFunc = functions
  .https.onCall(async (data) => {
    const firebaseApp = firebase.initializeApp({
      credential: admin.credential.applicationDefault(),
    });
    await firebaseApp
      .functions(PROJECT_A_FUNCTIONS_ROOT_URL)
      .httpsCallable('testFunc')(params);
  });

これで呼べるはず。

ポケモンUNITE モンスターPOP時間メモ

ポケモンUNITEにおいて重要となるモンスターの湧き時間メモ。
基本的にはカジリガメを真っ先に、可能な限り全力で殴りに行くべき。
ルカリオやゲンガーを使っていると異常なスピードで削ることができる。
カジリガメを殴るときは総力戦になりがちなので、ビークイン戦で相手に経験値を渡さないように頑張っておく必要がある。
2回ともカジリガメを取られた場合はほぼ絶望で、サンダーを食ってワンチャン狙おうにもレベル差ができているのでだいたい失敗に終わる。

モンスター 時間 補足
ヘイガニ 9:00 序盤の時間が余ってるときにちょろっとやっておく
ビークイン回目 8:50 1分30秒ごとに復活
カジリガメ 7:00 2分ごと復活
ロトム 7:00 2分ごと復活
サンダー 2:00 こいつが出たらカジリガメ・ロトムは出現しない

Prisma2 + Promise.all() とかやるとコネクション数制限に引っかかってエラーになる件

RDB に Prisma2 を用いてクエリを投げるのはよくやると思うんですが、Promise.all() とかして物凄い勢いで非同期実行するとこんなエラーが出がち。
あと connection_limit を引き上げろって言われてるけど、GCP のコンソールでグラフを見ている限り、実際には同時クエリ実行数で怒られてるように見える。

Timed out fetching a new connection from the pool. Please consider reducing the number of requests or increasing the connection_limit parameter (https://www.prisma.io/docs/concepts/components/prisma-client/connection-management#connection-pool). Current limit: 100.

.env の DATABASE_URLpool_timeout=0 を指定してやるとずっと待ってくれるので回避できる。
とはいえ 0 だと永久に待つらしいので、普通は 30sec 程度で殺すようにしたほうがいいと思う。
あと connection_limit, socketTimeout, connectTimeout の調整も必要であればやる。

DATABASE_URL=postgresql://postgres:postgres@localhost:5432/hoge?schema=public&connection_limit=100&pool_timeout=0&socketTimeout=0&connectTimeout=0