Amazon EBS ボリュームの拡張が本当にダウンタイムなしでできた
ボリュームサイズ変更後の Linux ファイルシステムの拡張 - Amazon Elastic Compute Cloud
↑のドキュメント見ながらやるだけです。
ファイルシステムがXFSなのかExt4なのかで、一部コマンドが違うので注意が必要ですが、特に難しいことはありませんでした。
最近ECSしか使ってないので、急に古いシステムのメンテナンスがあるとドキッとします。
ExoPlayerでhlsを流してみる
まずは、codelabsからコードをダウンロードしてきます。
https://developer.android.com/codelabs/exoplayer-intro?hl=ja#0
このコードラボのサンプルだとmp4とDASHの形式しか扱わないので、コードの修正が必要になります。
まずは、exoplayer-codelab-04
を有効化(インポート)するのがいいと思います。
app/build.gradleを下記のように変更します。
// ここだけ抜粋 dependencies { // Switch out the code lab step to jump to different points in the code lab implementation project(':exoplayer-codelab-04') // ←だけ変更 implementation 'androidx.multidex:multidex:2.0.1' }
また、hls用のライブラリを読み込まないといけないので、 exoplayer-codelab-04/build.gradle
に下記のように追加します。
そしてこの辺りを
private fun initializePlayer() { // ExoPlayer implements the Player interface player = ExoPlayer.Builder(this) .build() .also { exoPlayer -> viewBinding.videoView.player = exoPlayer // Update the track selection parameters to only pick standard definition tracks exoPlayer.trackSelectionParameters = exoPlayer.trackSelectionParameters .buildUpon() .setMaxVideoSizeSd() .build() val mediaItem = MediaItem.Builder() .setUri(getString(R.string.media_url_dash)) .setMimeType(MimeTypes.APPLICATION_MPD) .build() exoPlayer.setMediaItems(listOf(mediaItem), mediaItemIndex, playbackPosition) exoPlayer.playWhenReady = playWhenReady exoPlayer.addListener(playbackStateListener) exoPlayer.prepare() } }
このように修正します
private fun initializePlayer() { // ExoPlayer implements the Player interface player = ExoPlayer.Builder(this) .build() .also { exoPlayer -> viewBinding.videoView.player = exoPlayer // Update the track selection parameters to only pick standard definition tracks exoPlayer.trackSelectionParameters = exoPlayer.trackSelectionParameters .buildUpon() .setMaxVideoSizeSd() .build() val mediaItem = MediaItem.Builder() .setUri(getString(R.string.media_url_hls)) // 適当なhlsのurlを入手してください .setMimeType(MimeTypes.APPLICATION_M3U8) .build() exoPlayer.setMediaItem(mediaItem) exoPlayer.playWhenReady = playWhenReady exoPlayer.addListener(playbackStateListener) exoPlayer.prepare() } }
そして、playbackStateListenerの中身は、同じActivity内にこんなふうに定義しています。
private fun playbackStateListener() = object : Player.Listener { override fun onPlaybackStateChanged(playbackState: Int) { val stateString: String = when (playbackState) { ExoPlayer.STATE_IDLE -> "ExoPlayer.STATE_IDLE -" ExoPlayer.STATE_BUFFERING -> "ExoPlayer.STATE_BUFFERING -" ExoPlayer.STATE_READY -> "ExoPlayer.STATE_READY -" ExoPlayer.STATE_ENDED -> "ExoPlayer.STATE_ENDED -" else -> "UNKNOWN_STATE -" } Log.d(TAG, "changed state to $stateString") } // こっちだとhls(多分tsファイル)からメタデータが取れない override fun onMediaMetadataChanged(mediaMetadata: MediaMetadata) { mediaMetadata.description?.let { Log.d(TAG, "cmId: $it") } super.onMediaMetadataChanged(mediaMetadata) } // こっちだとhlsからメタデータが取得できる @androidx.media3.common.util.UnstableApi override fun onMetadata(metadata: Metadata) { Log.d(TAG, "metadata: $metadata") super.onMetadata(metadata) } }
これは、hls(多分tsファイル)からメタデータを取得するのを今のプロジェクトで行なっていたので、 自分でも行なってみたかったためです。
メタデータはmp4などだと、曲のタイトルや、アーティスト情報にあたるものです。
CloudFront Functionsでリダイレクト
CloudFront + S3の構成のwebサイトでリダイレクト処理をすることになりました。
S3にもリダイレクトの設定ができるようですが、今回はCloudFront Functionsを使いました。
CloudFrontにはWAFの設定などもあるので、CloudFront Functionsを使うことにより設定をより前の方に集めたかったのが、理由です。
実際に作成した関数は下記を参考にして作っています。
チュートリアル: CloudFront Functions を使用した単純な関数の作成 - Amazon CloudFront
今回は、301でのリダイレクトをしたいと思っているので、statusCode, statusDescriptionを変更し、さらにlocationを目的の場所に設定し直しました。
一見statusDescriptionは不要な気がしますが、実際には省略して、テストすると下記のエラーメッセージが表示されます。
The CloudFront function associated with the CloudFront distribution is invalid or could not run. Invalid status code desc,
なので、301であれば、statusDescriptionに'Moved Permanently'などを設定すれば良いと思います。
コードはこんな感じです。
function handler(event) { var response = { statusCode: 301, statusDescription: 'Moved Permanently', headers: { 'cloudfront-functions': { value: 'generated-by-CloudFront-Functions' }, 'location': { value: 'https://aws.amazon.com/cloudfront/' } } }; return response; }
最近rails書いてて気づいたこと
railsのEnumerableの拡張が便利
https://guides.rubyonrails.org/active_support_core_extensions.html#extensions-to-enumerable
ActiveRecordのpluckみたいな処理を、hashが要素になっている配列に対して行おうとした時に見つけました。
こういうのは、普通mapでやると思いますが、pluckで書くと若干シンプルになります。
require 'active_support/all' sample = [{ name: "David" }, { name: "Rafael" }, { name: "Aaron" }] mapped = sample.map { |e| e[:name] } plucked = sample.pluck(:name) # => ["David", "Rafael", "Aaron"] p mapped == plucked # true # 上記2つは同じ結果 sample2 = [{ id: 1, name: "David" }, { id: 2, name: "Rafael" }] p sample2.map { |e| [e[:id], e[:name]] } p sample2.pluck(:id, :name) # => [[1, "David"], [2, "Rafael"]] # 上記2つも同じ結果
vscodeのrubocopのプラグインが、GitHub Copilot並みに便利
というか、rubocopが便利というか、Copilotが何と言おうが、プロジェクトの決まり上、rubocopが正ということになったりもします。
最近の自分のプロジェクトでは、rubocop-railsまで入れてますが、
https://docs.rubocop.org/rubocop-rails/cops_rails.html#railsuniquevalidationwithoutindex
は、db/schema.rb の中身までチェックして、指摘してくれてるらしいです。
それと下記の2つは、こんなメソッド知らなかったみたいなものも教えてくれます
https://docs.rubocop.org/rubocop/cops_style.html#styleeachwithobject
https://docs.rubocop.org/rubocop/cops_style.html#stylefileread
ということで最近はrails書くときは、Copilotは無効化してます。
Android Studio Flamingoにアップグレードした時に古めのプロジェクトで起きたこと
環境
M1 macbook pro
起きたこと1
DSL element 'dexOptions' is obsolete and should be removed. It will be removed in version 8.0 of the Android Gradle plugin. Using it has no effect, and the AndroidGradle plugin optimizes dexing automatically.
これはFlamingoにした時にAGPを7.3.1にアップグレードした影響だと思います。これはapp/build.gradle
からdexOptionsのブロックを丸々消せるようになりますが、こういうのは地味に嬉しいです。
起きたこと2
How can I fix this error with ButterKnife in Android Studio? - Stack Overflow
↑で起きたことと全く同じ現象です。
いずれは、Butterknifeは使えなくなるんでしょうが、影響範囲が大きすぎておいそれと書き換えたりできないので、悩ましいです。
localstackのバージョンを上げたらSQS周りでハマった
上のissueに関係するものでした。タイトルにbugって書いてあるが、bugじゃなく仕様のようです。
バージョンアップ前は
# 環境変数 SQS_URL=http://localstack:4566/000000000000/app_name
# config/initializers/sqs_active_job.rb Aws::Rails::SqsActiveJob.configure do |config| config.logger = ActiveSupport::Logger.new($stdout) config.max_messages = 5 config.queues = { default: ENV.fetch('SQS_URL', nil) } config.client = Aws::SQS::Client.new(region: 'ap-northeast-1') end
こんな感じで指定していましたが、localstack/localstack:2.0.2
のdocker imageを使うようになってからエラーが発生するようになりました。
なので、環境変数で与えてる部分を
SQS_URL=http://localstack:4566/000000000000/ap-northeast-1/app_name
こんな感じで、regionを追加したら動くようになりました。
この方式は
https://docs.localstack.cloud/user-guide/aws/sqs/#queue-urls
に載っている、SQS_ENDPOINT_STRATEGY= path
にしたときと同じ動きですが、SQS_ENDPOINT_STRATEGYはどこにも指定して無いです。
githubのlocalstackのソースコードを読めばわかりそうな感じでしたが、そこまでする理由が今回は見当たらなかったので、そこで調査はやめています。
調査は楽しいですが、しすぎるのも良くないと最近思いました。
127.0.0.1の環境に置いたjavascriptからAPI Gatewayを呼ぶためのCORS設定
バックエンドはLambdaですが、Lambda自体は修正せずに上記の設定のみでいけます。