2020-02-01 マドリード・ダービー

昼前ぐらいにランニングのポイント練習をやる。太陽が出ていて、気温も高い印象。ここ最近は寒いのでウィンドウパーカーを着て走っているのだけど、久しぶりに半袖で走ることにした。少ない時間で効率よく練習するために坂道インターバルを試す。上り坂を全力で走って、下り坂をジョグする。これで心肺機能の向上と脂肪を燃焼しやすくする体質への改善を図る。やってみると距離や時間は普段のポイント練習より短いのだけど、なかなか苦しい。
終わった後に Garmin の測定結果をみたら、有酸素機能が「向上」、無酸素機能が「維持」で思っていたより効果がなかった。もう少しやってもよかったかなぁ。あんまり無理をすると今度は身体に負担がかかって、故障するので塩梅が難しい。
今後も週1回ぐらいの頻度でやる。

その後は部屋で一日をずっと過ごす。本を読んでメモをまとめたり、コーディングしたり、昨日書いた protobuf の件の issue を立てたりしていた。Proto3 repeated field not packed by default · Issue #345 · dart-lang/protobuf · GitHub
たまにはこういう日もあってもいいかなぁと思って、ずっと家にいたのだけど、若干気持ちが塞ぎがちになっていた気がする。天気もよかったし、どこかに出かけたほうがよかったかな。

その後は夕飯を食べて、マドリード・ダービーに備えて仮眠。11時前に目を覚まして、ライブ中継を見る。
前半立ち上がりはよいかんじで、堅守速攻のアトレティコらしい良い動きが出ていた。攻撃の基軸になっていたのはビトロとアンヘル・コレア。決定機が何回もあったのだけど、お互いにスコアレス。相手のカゼミーロの守備がよかった印象。前半に1点入れておきたかった...
後半開始直後、ジダンが調子の良かったクロースとイスコを下げて、 ヴィニシウスとルカス・バスケスを投入。フォーメーションをガラッと変えて、修正してきた。アトレティコは、この変化に対応しきれずに守備ラインが後ろに下がり、攻撃の基軸になっていたビトロも守備に時間を割かないといけなくなって、防戦一方という流れ。シメオネも交代カードを切るが、怪我人続出でリソースが足りていないアトレティコではこの状況を変えることはできなかった。結局、一瞬の隙を突かれて、ベンゼマに決められて、1-0 で試合終了。
ジダンの采配がお見事としか言いようがなかった... アトレティコは、この敗戦で6位に後退。前半の内容はよかったし、気を取り直して、次節がんばるしかない。

2020-01-31 アトレティコ、カバーニ獲得失敗、カラスコ復帰

1月ももう終わり。ここ数日は確定申告の準備で、昨年の会計データの内容を確認したり、必要な書類を集めたりしていた。用意した一式を毎年申告の書類作成をお願いしている税理士の人に送る。

仕事は久しぶりに Nuxt を書いているのと、バックエンドのAPIの実装。やりとりは gRPC Web でやっているのだけど、どハマりしてしまってつらかった(この件はまとめて改めてエントリを書く)。
端的に書くと protobuf の仕様をサーバーとクライアントそれぞれの言語の実装が満たしていないことによるものだった。dart の protobuf 実装は、デフォルトでエンコーディングすべきものをエンコーディングしていないのと(proto3 だとrepeatedフィールドのpackedエンコーディングはデフォルトで使用するはず)、js の protobuf 実装はエンコーディングされていなくてもパースできるはずのものをパースできなかった。
いったんは proto のファイルに [packed=true] を指定することで乗り切るけど、各ライブラリを本当は直すべき。

サッカーは冬の移籍マーケットが閉まる。アトレティコは、今シーズンの得点力不足を解消するために、ウルグアイ代表でパリ・サンジェルマン所属のエディソン・カバーニを狙っていたのだけど、移籍金の折り合いがつかなくて断念したらしい。うーん、数年前からシメオネカバーニの獲得を熱望していて、カバーニ本人も移籍したがっているという相思相愛の状況だったのに残念。ワールドクラスのストライカーなのにハードワークで献身的に守備をする、相方のフォワードを引き立てる黒子の役に徹することができる、というプレースタイルはアトレティコに合ってそうなので、夏のマーケットでぜひ来てほしい。
それとは別で、2018年にアトレティコから大連一方に移籍したベルギー代表のカラスコの復帰が決定。フォワードではないけれど、攻撃的ミッドフィールダーでドリブルがえぐい。ジョアン・フェリックスが怪我して、フォワード陣がモラタ、コレア、シャポニッチしかいない危機的な状況の中で明るい話題。明後日は、いよいよマドリードダービーなので楽しみ。

アトレティコ、マドリードダービーの前に不安が残る結果

朝起きて、疲労抜きジョグをする予定だったけれども雨が降っていたので中止。本を読んだり、コードを書いたりして9時ごろまで過ごす。

毎週日曜にやっている朝活のために表参道へ。ピースオブケイクのオフィスで、もくもくコードを書く。そこそこ集中できたかな。

13時ごろに表参道の清水湯へ。冷温交代浴で昨日のランニング練習の疲労を抜きたかったのだけど、入り口の靴箱に空きがないぐらい混雑していて断念。もうちょっと昼下がりに行かないとダメだなー。日曜の昼の表参道はどの店も混雑している印象。おとなしく帰宅。

適当にテレビを付けたら、テセウスの船の第一話の再放送をやっていて、面白そうだったので原作の漫画をKindleで買って一通り読んだ。面白かったけど、猟奇的な殺人犯が出てくるやつをタイムスリップで少しアレンジしたぐらいの内容かな、という感想だった。

相撲は初場所の千秋楽。正代の取り組みを見て、結びの一番まで時間があったので、それまで疲労抜きジョグ。太ももや股関節にダメージがきているなぁ。30分ほど走って戻ったら、ちょうど結びの一番。徳勝龍が貴景勝に勝って、優勝決定。うーん、正代との優勝決定戦が見たかったw 徳勝龍は場所中に大学時代の恩師の方が急逝されたらしく、並々ならぬ思いだったんだろうなぁ。勝った後に堪えられずに涙が流れていたのが印象的でした。
平幕の力士が力を付けてきていて、横綱大関を脅かしていたのが今場所の印象。世代交代が近づいてきているのかな。来場所も楽しみ。

20時からラ・リーガ 第21節 アトレティコvsレガネスをライブで見る。先週、国王杯のラウンド32でセグンダB(3部)のチーム相手に負けたので、ここで勝って気持ちを切り替えて、来週のマドリードダービー(vsレアル・マドリー)に繋げたい。にしても、都並敏史さんの解説はワイルドというか、選手に対する愛が溢れ出ていていいなぁ。
試合は相変わらず、守備の立ち上がりが悪くてヒヤヒヤすることが多数、後半主導権を握って相手のゴールに迫ることが増えたけれども、攻撃の厚みが足りなくて決まらない。終了間際にセルビアU21代表のシャポニッチが交代でリーガデビュー(多分)。普通にマッチしているかんじだったので、これからの活躍に期待。
結局、試合はスコアレスドローという結果。レアル・マドリー、今シーズン昇格で大物を食っているグラナダバレンシアリヴァプールと手強い相手との対戦が続く前の内容としては不安が残る... シメオネが解任されないか心配だ。

ひさしぶりの皇居ラン

ということで、ポイント練習のために久しぶりの皇居ランへ。一周5kmで適度に起伏がある皇居はポイント練習にちょうどいい。ランステは、いつものサクラホテル神保町。神保町駅から近くて、皇居にもすぐに行ける。シャワーにプラスして、走った後のご褒美のビールのセットもあって、 世界各地のビールが選べる。だれかと一緒に来た時は大抵これ。がんばってシャワーを浴びた後に飲むビールのうまいことうまいこと(本日はひとりなので飲まないけどね)。

皇居まで、準備運動がてら軽くジョグ。土曜なので、平日よりもランナーが多い印象。皇居に着いたら、タイムトライアル 5kmを2セットこなす。久しぶりに来たら、道が新しく舗装されている箇所があって、前よりも走りやすくなっていた。ゼーハーゼーハー言うまで追い込んだので、なかなかしんどいw

坂道のおかげもありそうだけど、1km、5km、10kmのタイムを更新!10kmをキロ4'36のペースで走った。久しぶりの記録更新なので、うれしい。Garminのトレーニングの効果の計測だと有酸素系はオーバーペースということだったので、負荷をかけすぎたかもしれない。無酸素系はそこそこの向上。無酸素系はスプリント走とか坂道インターバルで重点的にやったほうがいいかもしれない。

走り終わった後はご褒美で共栄堂のスマトラカレー。開店直後だったので、並ばずに入れた。スマトラカレーの独特のスパイスの香りがして、おいしい。走った後で身体が塩分を求めているからか、ちょっと塩をふって食べたら大正解。スマトラカレー、渋谷でもっと本格的なやつを食べたときは「うおっ!」ってなるぐらい香り?辛さ?が強烈だったのだけど、共栄堂のやつは日本人に合わせたマイルドな味。なんとなくビーフにしたけど、周りのオーダーを見てたらチキンが多かった。次はチキンも食べてみよう。

カレーを食べた後はなんとなく髪を切りたくなったので、渋谷へ。引っ越して半年以上経つけど、相変わらず旧居の近くのお店に通っている。早いし、安いんだよなぁ。髪を切った後は近くのハーツライトコーヒーへ。髪を切る場所を変えないのは、このお店かCONROW、うさぎに行く口実を作るためかもw
お店のお兄さんと、旧居の近くにあった自動車整備のお店やナイキの厚底シューズなどよもやま話。近くにできたカリカリスパイスというカレー屋がおいしいそうなので、今度いってみよう。

コーヒーを飲んだ後は Fab cafe などカフェを転々として、もくもく。どこも混んでるなぁ。区切りがいいところで、家に帰って相撲を見る。
優勝候補だった貴景勝が朝乃山に敗れて、レースから脱落。悔しそうな顔をしていたなぁ。アナウンサーが読み上げる「強くなって来場所帰ってきます」というコメントからも悔しさが滲み出ていた(本人の声じゃないんだけどw)。でも、互いにぎりぎりのところで踏みとどまって攻守が入れ替わる良い相撲だった。来場所も、朝乃山とのライバル対決が楽しみ。

ASP.NET Core のアプリで Firebase 認証

.NET Core の gRPC とか C# の Firestore クライアントを触る - kitak blog で書いたアプリに Firebase の認証を組み込む。具体的にはクライアントの Firebase SDK で生成した ID トークンの検証をおこない、ユーザーの id を取得する。.NET Core のバージョンは 3.1.0

ASP.NET Core には認証や認可の機能が含まれているので、Startup.cs でそれぞれのサービスとミドルウェアを登録してあげればよい。事前に利用する認証スキームのパッケージをインストールしておく。Firebase Authentication の場合は Microsoft.AspNetCore.Authentication.JwtBearer

dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer

サービスの登録

[Project ID] は Firebase のプロジェクトIDで置き換える。

public void ConfigureServices(IServiceCollection services)
{

    // ...

    services.AddAuthorization(options =>
    {
        options.AddPolicy(JwtBearerDefaults.AuthenticationScheme, policy =>
        {
            policy.AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme);
            policy.RequireClaim(ClaimTypes.Name);
        });
    });
    services
        .AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
        .AddJwtBearer(options =>
        {
            options.Authority = "https://securetoken.google.com/[Project ID]";
            options.TokenValidationParameters = new TokenValidationParameters
            {
                ValidateIssuer = true,
                ValidIssuer = "https://securetoken.google.com/[Project ID]",
                ValidateAudience = true,
                ValidAudience = "[Project ID]",
                ValidateLifetime = true
            };
        });

   // ...
}

ミドルウェアの登録

呼び出す順番が重要なので注意

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    // ...

    app.UseAuthentication();
    app.UseAuthorization();

    // ...
}

アクセスの制御

実際にアクセスを制御するには、制御したい gRPC のサービスのクラスかメソッドに Authorize 属性を指定する。ユーザーの情報は ServerCallContext から取得できる。

[Authorize]
public override Task<HelloReply> SayHello(HelloRequest request, ServerCallContext context)
{
    var user = context.GetHttpContext().User;
    var uid = user.Claims.Where(claim => claim.Type == "user_id").FirstOrDefault().Value;
    
    // ...
}

.NET Core アプリを Cloud Run にデプロイする

.NET Core の gRPC とか C# の Firestore クライアントを触る - kitak blog で書いたアプリを Cloud Run にデプロイしてみた。

Docker を使用してアプリをコンテナー化するチュートリアル - .NET Core | Microsoft Docshttps://cloud.google.com/run/docs/quickstarts/build-and-deploy?hl=ja を参考に進めた。

Dockerfile は、こんなかんじ。

# Use Microsoft's official lightweight build .NET image.
# https://hub.docker.com/_/microsoft-dotnet-core-sdk/
FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS build
WORKDIR /app

# Install production dependencies.
# Copy csproj and restore as distinct layers.
COPY *.csproj ./
RUN dotnet restore

# Copy local code to the container image.
COPY . ./
WORKDIR /app

# Build a release artifact.
RUN dotnet publish -c Release -o out

# Use Microsoft's official runtime .NET image.
# https://hub.docker.com/_/microsoft-dotnet-core-aspnet/
FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS runtime
WORKDIR /app
COPY --from=build /app/out ./
ENV ASPNETCORE_ENVIRONMENT Production
ENV PORT 8080

# Run the web service on container startup.
ENTRYPOINT ["dotnet", "GrpcGreeter.dll"]

Cloud Run にデプロイするにあたって、Program.csCreateWebHostBuilder の定義を以下のように書き換える。ポートを環境変数で指定できるようにするのと、IPアドレス0.0.0.0 にする。

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(webBuilder =>
            {
                string port = Environment.GetEnvironmentVariable("PORT") ?? "8080";
                webBuilder.ConfigureKestrel(options =>
                {
                    // Setup a HTTP/2 endpoint without TLS.
                    options.Listen(IPAddress.Any, int.Parse(port), o => o.Protocols = 
                            HttpProtocols.Http2);
                });
                webBuilder.UseStartup<Startup>();
            });
    }

イメージのビルド&デプロイはドキュメントの通りで、

gcloud builds submit --tag gcr.io/[PROJECT-ID]/greeter

gcloud beta run deploy --image gcr.io/[PROJECT-ID]/greeter

で、とっても簡単。

ちょっと前まで Windows だけでしか動かなかったサービスが Googleクラウドで動くのだから、すごい時代(コンテナ・ Docker が普及したのが大きそう)。

デプロイしたサービスのシャットダウンは GCP のコンソールから行う。

足の治療院に行ってきた 2020年1月

毎月行っている足の治療院へ。

ちょうど数日前にビルドアップ走をしてから、足首やら足の付根が痛くなっていたので、相談に乗ってもらった。日に日に痛みはなくなってきているので、普通に負荷がかかりすぎたんでしょう、とのこと。

心肺機能を向上させるために、週に1,2回、ゼーハーゼーハー言いながら走っているのだけど、そこまで追い込むと足にけっこうなダメージが与えているという課題が浮き彫りになった。筋肉が硬くて動きが悪いのを無理に動かそうとして、足がダメージを受けているので、ストレッチで筋肉を柔らかくして身体を動かしやすくしましょう、という話になった。
具体的には走り終わった後とかお風呂に入った後に、ふくらはぎ、腿前、腿裏、お尻の静的ストレッチを5分以上やる。アプリとか Pixela で記録をつけるといいかも。