カフェでMacを開きたい

仕事とか技術とか趣味とか

Redisのexpireが全然効かない

結論

expireを設定した後にそのキーに対してsetし直すと、expireの設定が消える。

概要

ゴミデータが溜まっていく

仕事で関わっているシステムの一部にredisが組み込まれていて、以下のような流れでkeyとvalueをセットしていた。

  1. アプリケーションサーバーからジョブサーバーの処理開始APIを叩く
  2. ジョブサーバーの処理開始APIでは、ジョブをキューイングしつつ処理結果を保存するためのレコードをredisにexpire付きで用意して、keyをアプリケーションサーバーに返却する
  3. ジョブが非同期で実行され、処理結果がsetされる
  4. アプリケーションサーバーは受け取ったkeyを元にジョブサーバーの結果取得APIを定期的に叩いて、処理結果を取得する

この時、expireを設定しているにも関わらず、なぜか一件も削除されずに不要なデータがどんどん溜まっていってしまっていた。

redisのプロセスが途切れる?

以下の記事を見つけて試してみるも、やはりデータは残り続けてしまう。
qiita.com

でもどうやら安易にexpireを設定すると効かない場合があるらしい。

ドキュメントにあった…

ちゃんとredis公式に書いてあった。。。
redis.io

The timeout will only be cleared by commands that delete or overwrite the contents of the key, including DEL, SET, GETSET and all the *STORE commands.

値を上書きすると消えるよとのこと。
今回でいうと、枠を確保する時ではなく処理結果を保存する時に、expireを設定するべきだった。

まとめ

公式ドキュメントはやはり真っ先に調べるべきだった…。
何も考えずに安易にexpireを設定してしまうとちょっとハマる可能性がある。

AWS API Gatewayでapplication/x-www-form-urlencodedの配列パラメータを扱いたい時のマッピングテンプレート

hoge[]を受け取りたい

AWS LambdaとAPI Gatewayを連携させてPOSTを受け取って・・・とやろうとした時に、配列のパラメータの扱いで少しハマりました。

application/x-www-form-urlencodedの単純なkey=valueのPOSTを扱うマッピングテンプレートは、ググればたくさん出てくるんですが、key[]=valueの配列を扱えるものはほとんど出てきませんでした。

唯一まとめてくださっていたのが以下の記事。

takigawa401.hatenablog.com

こちらの記事のテンプレートをコピペしても動くんですが、リクエスト時のパラメータの状態によって整形後のjsonが不正な形式(浮いたカンマがある)になる場合があったので、自分なりにちょっと改造をしてみました。

テンプレート

{
    "headers" : {
        #foreach( $key in $input.params().header.keySet() )
            "$key" : "$input.params().header.get($key)"#if( $foreach.hasNext ),#end
        #end
    },
    "queryParameters" : {
        #set( $tmpStr = $input.path('$') )

        ##配列をまとめるハッシュと単純な値をまとめるハッシュ
        #set( $arrayKeyValue = {} )
        #set( $simpleKeyValue = {} )

        #foreach( $keyAndValueStr in $tmpStr.split( '&' ) )
            #set( $keyAndValueArray = $keyAndValueStr.split( '=' ) )

            #if( $keyAndValueArray[0].indexOf('[]') > 0)
                ##「key[]=value」を「key : [value]」に変換してまとめる
                #set($arraykey = $keyAndValueArray[0].substring(0, $keyAndValueArray[0].indexOf('[]') ))
                #set($arrayvalue = [])
                
                #if($arrayKeyValue.containsKey($arraykey))
                  #set($arrayvalue = $arrayKeyValue.get($arraykey))
                #end
                
                #set($dev_null = $arrayvalue.add($keyAndValueArray[1]))
                #set($dev_null = $arrayKeyValue.put($arraykey, $arrayvalue) )
                
            #elseif( $keyAndValueArray[0].indexOf('%5B%5D') > 0)
                ##「key[]=value」を「key : [value]」に変換してまとめる(上と全く同じことをやっている)
                #set($arraykey = $keyAndValueArray[0].substring(0, $keyAndValueArray[0].indexOf('%5B%5D') ))
                #set($arrayvalue = [])
                
                #if($arrayKeyValue.containsKey($arraykey))
                  #set($arrayvalue = $arrayKeyValue.get($arraykey))
                #end
                
                #set($dev_null = $arrayvalue.add($keyAndValueArray[1]))
                #set($dev_null = $arrayKeyValue.put($arraykey, $arrayvalue) )
                
            #else
                ##単純な「key : value」でまとめる
                #set($dev_null = $simpleKeyValue.put($keyAndValueArray[0], $keyAndValueArray[1]) )
            #end
        #end
        
        ##「key : value」を書き起こす
        #foreach( $key in $simpleKeyValue.keySet())
            "$key" : "$util.urlDecode($simpleKeyValue.get($key))"#if($foreach.hasNext() || $arrayKeyValue.size() > 0),#end
        #end
        
        ##「key : [value]」を書き起こす
        #foreach( $key in $arrayKeyValue.keySet())
            #set( $resultValArr = $arrayKeyValue.get($key) )
            "$key" : [#foreach($val in $resultValArr)"$util.urlDecode($val)"#if($foreach.hasNext()),#end#end]#if($foreach.hasNext()),#end
        #end
    },
    "stage" : "$context.stage",
    "sourceIp" : "$context.identity.sourceIp",
    "userAgent" : "$context.identity.userAgent"
}

解説とまとめ

単純なkey=valueをまとめるハッシュと、配列のkey[]=valueをまとめるハッシュを別にしました。

最初にパラメータを分解してハッシュに一通りまとめて、最後にいっぺんに文字列として書き起こしていく流れです。

参照元の記事では、配列をハッシュにまとめている間に単純なkey=valueは文字に起こしていたのですが、個人的に「分解→整形」の流れにした方が分かりやすかったので、別々の変数にまとめました。

これでどんなパラメータがきても対応できると思います。

一つ注意といえば、数値も全部文字列にしてしまうので、受け取る側で適宜型変換をしないと行けない点ですね。

application/x-www-form-urlencodedだと結構面倒ごとが多いから大人しくapplication/jsonで送ってもらうのが良いのかもしれません・・・。

会社員からフリーランスエンジニアになる時のリアル環境構築

概要

フリーランスになってから丸3ヶ月経ちましたが、役所関係の様々な手続きをサボっていたためにヒィコラ言いながらやる羽目に・・・。環境構築は開発もリアルもものすごく重要ですね。

ここまでやっておけばとりあえず業務に集中できる環境は作れる、というものをまとめた記事があまりないように思ったので、備忘録も兼ねてまとめておきます。

と言ってもほとんど税と社会保険ですが・・・。

やらなきゃいけないこと

開業届、青色申告承認申請書の提出

大前提の手続きです。管轄の税務署に提出します。

最大65万円控除を受けられる青色申告の承認申請書は、開業日から2ヶ月以内であればいつでも提出できますが、どうせ書く内容はほとんど一緒なので一緒に出してしまいます。

会社員のうちから提出できるので、退社日などが決まったらさっさと出してしまった方が良いです。

一つ注意として、屋号を決める場合は自分の名前以外のものにすることをおすすめします。

営業性個人の銀行口座を開設する際、屋号が氏名と同じだと開設できないことがあるからです。

ちなみに自分は開業freeeの無料ツールを使って両方作成してしまいました。必要事項を入れてサクッと作成、印刷後にハンコを押して投函するだけだったのでめっちゃ楽でした。

営業性個人銀行口座の開設

個人事業主になると、税理士さんなどにお願いしない限り、書類の保管など含め全ての税務作業を自分でやる必要があります。

自分もまだやり始めたばかりですが、普段から整理しておかないとかなり面倒です・・・。

お金の出入りを分かりやすくするために、事業用の口座と私的な口座を分けましょう。

会社員時代に使っていた口座を私的なものにして、事業用の口座を新たに開設するのが分かりやすくて良いと思います。

営業性個人口座の開設には、開業届の控えが必要なので、上記の書類提出後にやりましょう。

これも開業freeeの無料ツールで簡単にできちゃいます。(自分は開業freeeの関係者ではないです、本当に楽で助かったんです)

国民年金国民健康保険の申し込み

会社を辞めると、それまで入っていた健康保険の資格喪失証明書が会社から送られてくると思います。

これとその他必要なものを持って役所に行き、国民年金国民健康保険の手続きを済ませましょう。

国民年金は払わなくていいとか払わなくてもいけるとかチラホラ聞きますが、加入は義務のため、未払いがバレると口座凍結されたりします。

健康保険については、事業内容によっては保険料が安い他の健保に加入できる場合もあるので、一度調べてみた方が良いかもしれません。

やっておいた方が良いこと

個人事業主になるために、なった後に必要なものは上記で全部ですが、他にもやっておくと諸々捗るんじゃないかなーと思うことを並べていきます。

マイナンバーカードの作成

開業届含め、様々な手続きでマイナンバーが必要になります。

マイナンバーの証明には、マイナンバーカードやマイナンバー付きの住民票が必要になりますが、保管しやすく有効期限の長いカードの方がおすすめです。

管轄税務署主催の説明会への参加

開業すると、税務署から日々の税務や申告についての説明会の案内が送られてくる場合があります。

自分の自治体では結構丁寧な資料をもらえて、説明も親切で分かりやすかったので、一度参加してみると良いかもしれません。

業務用クレジットカードの作成

事業用の口座から引き落とされるクレジットカードを別で作っておくと、お金の記録が楽になります。

事業用の買い物をする場合はなるべく現金ではなく事業用カードで払う、というルールを徹底すると良いと思います。

ちなみにこれも開業freeeで作れます。

税務関係の書類の管理ルールの徹底

とりあえず私的なものも含め、レシートや領収書は全て取っておきましょう。何かあった時の証拠、武器になります。

事業に関係するお金の出入りがあった時は、早めの記帳を忘れずに。

簿記の勉強

税務の基本的な知識を身につけるために、簿記3級レベルで良いので勉強しておくと良いと思います。

知識があれば作業に対するハードルを下げることができ、応用も効くようになります。

参考書は経費で落としましょう。

まとめ

ここまでやっておけば、業務以外で詰まるということはあまりないんじゃないかなと思います。

業務以外のことが苦になりにくい環境を作って、お仕事に集中できるようにしたいですね。

ランダムなSCP記事を3つ返すLINE BOTを作った

概要

「暇」「ランダム」などの言葉を入力すると、ランダムなSCP記事を3つ返してくれるLINE BOT、「Search, Crawl, Pick」を作ってみました。
また、アイテム番号を半角数字で入力すると、それに対応した記事を返します。
(和訳ページが存在するもののみ返します。)

f:id:shintaro-mori:20181004140650p:plain:w200

オールドAIを利用して財団データベースにアクセスしているので、彼の機嫌が悪い時はデータが返りません。

f:id:shintaro-mori:20181004142719p:plain:w200

友達登録はこちらからお気軽にどうぞ。


中身の話

サーバー

GASで実装してサーバー代わりにしています。
ユーザーデータが必要なわけでもないし、SCPの総データもたかだか最大5000件なので、スプレッドシートをDB代わりにしちゃってます。

データの取得

SCP一覧ページをスクレイピングしてタイトルやアイテム番号を取得し、スプレッドシートに入れるスクリプトPythonで書きました。
自宅のラズパイから1日1回cronで起動することで情報を最新化しています。

bot

ただ定型単語に反応するだけです。
「ランダム」「適当」「てきとう」「暇」「ひま」の5単語を入力すると、ランダムな3記事を返します。
半角数字のみ入力するとアイテム番号と解釈し、それに対応した記事を返します。
おまけで、特定の数字については対象のSCPに沿った内容を返します。

オールドAIの割り込みは、全入力に対して約1/20の確率で発生します。


「これを読め!」が欲しかった

SCPが好きでよく読むんですが、まー記事の数が多いので能動的に読むのが結構つらい。

だいたい一覧ページをだらだらスクロールして、パッと目についたタイトルの記事を読むんですが、どうしても偏ってきちゃうんですよね。

一応PCページには「ランダムページ」の項目があるんですが、スマホにはなく・・・

ちょうどお仕事でLINE BOTに関係することをやっていたので、勉強がてら作ってみようと思って作りました。

数件の記事を読め!と出されるとやっぱり読みやすいですね。これでちょっとした空き時間の暇つぶしが超捗ります。