OmniAICreator/Qiita-1.07M huggingface dataset:
treeを用いて区間内の特定の要素の個数をlogの2乗で求めるデータ構造

# はじめに
こんにちは。mofuuniです。
今回は、タイトルにもある通り __「treeを用いて区間内の特定の要素の個数を$O(log^2N)$で求めるデータ構造」__ というものを作ったので紹介したいと思います。

<font color="Red">※2024/4/4追記 多数の間違いを発見したため大幅に修正しました。</font>
# できること
次のクエリに答えることができます。
1. $A_{pos}$の値を$A_{pos}⋆x$に変更せよ。
2. $A_l, A_{l+1}, ..., A_r$の中に含まれる$x$の個数を答えよ。

計算量はどちらも$O(log^2N)$です。
# 実装
```cpp
#include <bits/stdc++.h>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/tree_policy.hpp>
#include<ext/pb_ds/tag_and_trait.hpp>
using namespace std;
using namespace __gnu_pbds;
template<class T> using Tree=tree<T,null_type,less<T>,rb_tree_tag,tree_order_statistics_node_update>;

template<class T>
class FreqencyCountTree{
    public:
    using OP=function<T(T,T)>;
    vector<T> vec;
    map<T,Tree<int>> data;
    OP op;
    FreqencyCountTree(int n,T init):vec(n+1,init){
        for(int i=1; i<=n; i++)data[init].insert(i);
        op=[](T a,T b){return b;};
    }
    FreqencyCountTree(int n,T init,OP op_):vec(n+1,init),op(op_){
        for(int i=1; i<=n; i++)data[init].insert(i);
    }
    FreqencyCountTree(vector<T> v):vec(v){
        for(int i=1; i<v.size(); i++)data[v[i]].insert(i);
        op=[](T a,T b){return b;};
    }
    FreqencyCountTree(vector<T> v,OP op_):vec(v),op(op_){
        for(int i=1; i<v.size(); i++)data[v[i]].insert(i);
    }
    void update(int pos,T x){
        data[vec[pos]].erase(pos);
        vec[pos]=op(vec[pos],x);
        data[vec[pos]].insert(pos);
    }
    int count(int l,int r,T x){
        if(l>r)return 0;
        if(!data.count(x))return 0;
        int lef=data[x].order_of_key(l);
        int rig=data[x].order_of_key(r+1);
        return rig-lef;
    }
};
```
名前は仮です。
# 説明
## vec
元の配列のコピーです。
## data
$A_{pos} = x$のとき$data[x]$の中に$pos$を入れます。
つまり、「$A$の何番目が$x$か」ということです。
## op
値を変更する演算です。指定しなければ代入になります。
## update関数
クエリ1をこなします。計算量は$O(log^2N)$です。
## count関数
クエリ2をこなします。
treeのorder_of_key関数により$data[x]$内の$l$未満の要素の個数($l$より前に$x$が何個あるか)、$r$以下の要素の個数($r$までに$x$が何個あるか)を数え、引くことで区間内の$x$の個数が求まります。
計算量は$O(log^2N)$です。
# verify(問題のネタバレを含みます)
<details><summary>verify</summary>

[ABC248 D - Range Count Query](https://atcoder.jp/contests/abc248/tasks/abc248_d)
要素の個数のみです。

[ABC343 F - Second Largest Query](https://atcoder.jp/contests/abc343/tasks/abc343_f)
想定解ではSegment Treeに4つも情報を載せるので大変なところを楽できます。
ちなみにこのデータ構造はこの問題を考えているときに思いつきました。


[C: Range Same Query](https://onlinejudge.u-aizu.ac.jp/challenges/search/titles/3326)

[ABC157 E - Simple String Query](https://atcoder.jp/contests/abc157/tasks/abc157_e)
数列以外でも使えます。
</details>

# おわりに
初めての執筆でわかりにくいところも多々あったかと思いますが、最後まで読んでくださりありがとうございました。
ご指摘・ご質問等ございましたらお気軽にどうぞ。
CloudFrontとは？？

## 初めに
前回、[CDN](https://qiita.com/h3iak7i/items/e794b98f40919381533e)に関して投稿させて頂きました。
今回は、AWSのCDNサービス「CloudFront」に関して書かせて頂きます。

## Amazon CloudFrontとは？
動画やアプリケーション、動的・静的なコンテンツを迅速に配信できるCDNサービスです。

世界中にエッジサーバーがあり、どこからのアクセスに対して柔軟に対応できる為、低レイテンシーでコンテンツ提供が可能になります。

## 仕組み
![スクリーンショット 2024-03-26 17.20.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3744656/a94e189d-85b4-92f1-713a-c0351ff39740.png)

①\. エッジローケーションにコンテンツがない場合
    オリジンサーバーから取得して返却する。
    その際、エッジロケーションにキャッシュする。
    
②\. エッジローケーションにコンテンツがある場合
    　そのまま、キャッシュされているコンテンツを返却する。
    


## 用語解説
①\. エッジローケーション
    エッジサーバーの事。
    世界中に存在しており、利用頻度の高いコンテンツをキャッシュ(保存)します。
    →グローバル配信をサポート

②\. オリジン
    オリジンサーバーの事。
     WebサーバーやAPサーバー、S3バケットを加える事が出来る。

③\. ディスクトリビュージョン
    インターネット上に存在するサーバーなどの個々の名前（ドメイン）ごとに作成される設定の集合体

## 料金
①\. HTTP/HTTPSリクエスト時
→リクエスト数に応じて課金

②\. オリジンへのデータ転送時
→データ量に対してGB単位で課金

③\. インターネットへのデータ転送時
→データ量に対して課金

## 最後に
CloudFrontを使用する事により、コンテンツ配信のパフォーマンスが向上します。
コンテンツ配信サービスをご検討されている方は、ぜひ使ってみてください！
WindowsでEB CLIのインストールをしようとしたときにエラーになった

# エラー内容
https://docs.aws.amazon.com/ja_jp/elasticbeanstalk/latest/dg/eb-cli3-install.html

このチュートリアルにあるGithubページから`aws-elastic-beanstalk-cli-setup`をクローンし、READMEに書いてあるとおり、以下のコマンドをコマンドプロンプトで実行したところ、
```shell
python .\aws-elastic-beanstalk-cli-setup\scripts\ebcli_installer.py
```

以下のエラーが出た。

```shell
ERROR: Could not find and "virtualenv" installed. Ensurevirtualenv is installed and that it is in PATH before executingthis script.
```

`aws-elastic-beanstalk-cli-setup`のGithubページのREADMEのTroubleShootingに以下のように書いてあったので、コマンドを順番に実行したところ、

> If you encounter an error with the message "No module named 'virtualenv'", use the following commands to install virtualenv and the EB CLI:
> ```shell
> pip uninstall -y virtualenv
> pip install virtualenv
> python .\aws-elastic-beanstalk-cli-> setup\scripts\ebcli_installer.py
> ```

以下のエラーが出た。
```shell
WARNING: Failed to write executable - trying to use .deleteme logic (以下省略)
```

# 解決策
管理者権限でコマンドプロンプトを開いてからコマンド実行した。
```shell
pip uninstall -y virtualenv
pip install virtualenv
python .\aws-elastic-beanstalk-cli-setup\scripts\ebcli_installer.py
```

# 参考

https://yusu79.com/pip-install-failure-fix/
Proxmox8 を試してみる　その１９　noVNCが開けない（クラスタ参加/削除が原因）

# noVNCが開けない
リストアしたVMを立ち上げようとProxmoxのWebGUIからコンソールを表示すると、”noVNCが開けない” となりました。しかもProxmox状態をみると `エラー：Failed to run vncproxy.` と表示されているしお手上げ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44540/f62e88d6-b754-d354-5317-38adcc1b935a.png)

と思ったら。原因がわかりました。

# ノード証明書が異なるとエラー：Failed が発生
クラスタ環境を構築したあとにノード側でProxmoxを再インストールした場合に発生するようです。具体的には、Proxmoxの再インストールを行った際に同じホスト名（=ノード名）とした場合、マスタクラスタ側で管理しているSSH証明書に齟齬が発生するためのようです。

実際、エラーの詳細を見ると下記が出力されていました。

```text
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!

Someone could be eavesdropping on you right now (man-in-the-middle attack)!

It is also possible that a host key has just been changed.

The fingerprint for the RSA key sent by the remote host is
SHA256:rVnjjR/mueG9rysSaASRyFJOqmleVSlC5zPVtqxPD9c.

Please contact your system administrator.

Add correct host key in /root/.ssh/known_hosts to get rid of this message.

Offending RSA key in /etc/ssh/ssh_known_hosts:9

  remove with:

  ssh-keygen -f "/etc/ssh/ssh_known_hosts" -R "sea-bird4"

Host key for sea-bird4 has changed and you have requested strict checking.

Host key verification failed.

TASK ERROR: Failed to run vncproxy.
```

# どうしたらいいのか！
今回だめになっているノードは　`sea-bird4` (192.168.0.8) なのでマスタクラスタ側で以下のコマンドを実行する。

```bash
# /usr/bin/ssh -e none -o 'HostKeyAlias=sea-bird4' root@192.168.0.8 /bin/true
The authenticity of host 'sea-bird4 (192.168.0.8)' can't be established.
ED25519 key fingerprint is SHA256:UXWuGBsGgHhVfQQvwGSg7v33hXiMv/DB/hPoMRFQ.
This host key is known by the following other names/addresses:
    ~/.ssh/known_hosts:1: [hashed name]
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'sea-bird4' (ED25519) to the list of known hosts.
```

# 参考にさせて頂いたサイト様

https://wp.jisaba.life/2021/05/05/post-1610/
記事を公開する前に確認していること

こんにちは。
この記事では、私が記事を公開する前に確認していることを書いていきたいと思います。
私はまだ初心者ですが、少しでも参考になれば嬉しいです。

# 不自然な日本語
記事投稿サイトでは、相手に伝わりやすい記事を書くといいと思います。
そこで、公開する前に不自然な日本語を探します。

## 例1

以下の文章を直してみましょう。
```text:不自然なテキスト.txt
本日はPythonの最新トレンドについて語ります。
```

以下は、Pythonのライブラリを紹介する記事の場合の、直し方の例です。
```text:不自然なテキスト_修正済み.txt
この記事では、Pythonでよく使われているライブラリを紹介します。
```

### 修正点

1. `本日` を `この記事で` に変更
     - セミナーではなく記事なので、言い方を変更しました
2. `、` を追加
     - 読みやすくするために、追加しました
3. `の最新トレンドについて語ります。` を `でよく使われているライブラリを紹介します。` に変更
     - 語っているのではなく、紹介しているので、変更しました

# 説明不足
説明が足りていない記事の場合、説明を増やしましょう。
プログラムを添付している場合、コメントなどで対応しましょう。

## 例1

```text:説明が不足しているテキスト.txt
Pythonがおすすめです。
```

```text:説明が不足しているテキスト_修正済み.txt
Pythonは、公開されているライブラリが多いので、おすすめです。
例えばpygameは、Pythonで動くゲームエンジンのライブラリです。
```

### 修正点

1. 理由を追加
2. 例を追加

## 例2

```text:コメントが少ないPythonプログラム.py

number = 1 + 2
print( number )

```

```text:コメントが少ないPythonプログラム_修正済み.py

number = 1 + 2 # 1 + 2 を計算し、numberという変数に保存。
print( number ) # numberという変数の内容を読んで、print関数で出力する。

```

### 修正点

1. コメントを追加

# 書ききれなかったこと
以下の内容は書ききれませんでした。

1. 誤字脱字の修正
2. 開発環境を書く (プログラミングの場合)
3. プログラムのバグの修正 (プログラミングの場合)

# まとめ
記事を公開する前に内容を確認することで、読みやすい記事にすることができます。
axiosの代わりにky使ってみた

## kyとは
https://github.com/sindresorhus/ky

☝️こちらを参考

## axiosとの違い
ChatGPTさん曰く
>kyとaxiosは、両方ともHTTPクライアントライブラリであり、HTTPリクエストを行うための便利なインターフェースを提供しますが、いくつかの違いがあります。

> APIのデザイン:
> axios: PromiseベースのAPIを提供し、非同期処理を簡単に行うことができます。Node.jsとブラウザの両方で使用できます。また、エラー処理、リクエスト/レスポンスの中断、HTTPリクエストのキャンセルなど、さまざまな機能を提供しています。
ky: fetch APIに基づいた簡潔なAPIを提供しています。fetch APIと同様に、Promiseベースの非同期処理を行います。ブラウザでのみ使用可能で、Node.jsでは動作しません。

> ブラウザとNode.jsのサポート:
axios: ブラウザとNode.jsの両方で使用可能です。
ky: ブラウザでのみ使用可能で、Node.jsでは動作しません。

> サイズ:
axios: 比較的大きなライブラリですが、多くの機能を提供します。
ky: 軽量であり、単純なHTTPリクエストの場合に最適です。

> 機能:
両方とも、HTTPリクエストの送信、レスポンスの処理、エラーハンドリングなど、基本的な機能を提供します。ただし、axiosはより多くの拡張機能を提供し、リクエストのキャンセルやインターセプターなどの高度な機能を利用できます。

計量プロジェクトで特に拡張的なHTTPリクエストとかしなければkyを選定してみるのが良いかもしれない。

## インストール
``` 
pnpm i ky
```

## postの実装
``` typescript:
  // ヘッダ
  const headers = {
    'Content-Type': 'application/json',
  };
  // jsonデータ
  const json = {
    data: 'test'
  };

  await ky.post('http://localhost:8080', {headers, json});
```

## まとめ
HTTPrequestも色々出てきてるんだなぁと。
よく使っていたaxiosを問答無用で使ってたので、技術仕様の際に、一旦他のないかなと探してみるのもありだなと思った。
iTerm2 の shell integration で文字拡大できなくなった時の対処

# はじめに

iTerm2 の文字を拡大するショートカット 「 Command+ "+" 」 にて、拡大する代わりに以下のダイアログが出て、邪魔される事がありました。その対処メモです。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1798/979bfbef-aae0-a04f-cd9d-cec280d613f2.png" width="50%">

# Shell Integration の Install

Shell Integration をインストールするまで何度でもこのダイアログが出て、拡大できません。観念して一旦インストールします。(Cancel もしくは No Need 的なボタンがないんですよね。。)

すると、Command + "+" で、以下のようなヒストリー(?)がポップアップ表示されるようになります。

![スクリーンショット 2024-03-26 16.33.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1798/f8ffc1c4-5792-842a-34f1-2b7de2210466.png)

# Shell Integration の無効化

ちなみに、Shell Integraion の Install を実行すると、ログイン先の $HOME に以下のファイルが展開されます。

```
% ls .iterm2*
.iterm2_shell_integration.bash

.iterm2:
imgcat		it2attention	it2dl		it2profile	it2tip
imgls		it2check	it2getvar	it2setcolor	it2ul
it2api		it2copy		it2git		it2setkeylabel	it2universion
```

このうち .iterm2_shell_integration.bash を削除するか、別の名前に変えることで、無効化できるようです。(zsh を使っている場合は、これの zsh 版で同様の操作すれば OK のはず)

```
% mv .iterm2_shell_integration.bash .iterm2_shell_integration.bash_
```

この後、iTerm2 アプリを一旦終了させます。
グローバルメニューの Quic iTerm2 もしくはドックのアイコンから 終了から実行可能です。
(なお、端末のウィンドウだけ終了させても駄目なようです)

| global menu | dock icon menu |
|---|---|
| ![スクリーンショット 2024-03-26 16.45.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1798/78a54c71-a7f8-19f3-ad9f-50ce51fe5b84.png) | ![スクリーンショット 2024-03-26 16.45.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1798/12388c21-600f-7475-7fa3-11b1613e356f.png) | 

この後、iTerm2 を起動し直せば、Command + "+" での文字拡大機能が復活します。

# 参考URL

- How to disable or uninstall shell integration in v3?
  - https://groups.google.com/g/iterm2-discuss/c/GbXOOaJDhvk/m/-mmgUwarAAAJ
```
Look in your ~/.profile, ~/.bash_profile, ~/.login, ~/.zshrc, or ~/.config/fish/config.fish (which file it's in depends on what shell you use) for a line like this:

test -e "${HOME}/.iterm2_shell_integration.bash" && source "${HOME}/.iterm2_shell_integration.bash"

And remove it.
```
PythonでExcel (XLS/ XLSX)をPDFに変換する

PDFにExcelファイルに変換すると、印刷や共有文書に加えて、フォームデータの保存を容易にすることができますまた、フォームのスタイルなどのレイアウトは、異なるデバイスやオペレーティングシステムでの一貫性を維持することを確認することができます。 今日は、ExcelをPDFに変換する簡単な方法を実現するサードパーティのPythonライブラリ[**Spire.XLS for Python**](https://www.e-iceblue.com/Introduce/xls-for-python.html) を紹介します。

### Excel to PDFの実装手順
1.	まず、pipコマンドで依存ライブラリをインストールします；
`pip install Spire.XLS`
2.	インストールが完了したら、必要なライブラリをインポートします；
3.	Excelドキュメントをロードし、Spire.XLS for Pythonが提供する**Workbook.SaveToFile()** または**Worksheet.SaveToPdf()** を使用して、Excelワークブックまたは指定したワークシートをPDF形式に変換することができます;
4.	また、**PageSetup**クラスを使用して、変換中にページ設定を行うこともできます。

:point_down:
**コード例**

### 1. Pythonを使ってExcelファイルをPDF形式に変換する（各ワークシートは別々のページとして表示される）：
```python
from spire.xls import *
from spire.xls.common import *
 
# Workbookオブジェクトの作成
workbook = Workbook()
 
# エクセル文書を読み込む
workbook.LoadFromFile("Input.xlsx")
 
# ワークシート適応ページの設定
workbook.ConverterSetting.SheetFitToPage = True
 
#エクセルをPDFに変換する
workbook.SaveToFile("ExceltoPDF.pdf", FileFormat.PDF)
workbook.Dispose()
```
![ExcelからPDFへ.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2811193/fc2ebdf9-01bd-0239-e3e5-ed68b218624f.jpeg)

### 2. Pythonを使って、Excelの各ワークシートを別々のPDFファイルに変換する：
```python
from spire.xls import *
from spire.xls.common import *
 
# Workbookオブジェクトの作成
workbook = Workbook()
 
# エクセル文書を読み込む
workbook.LoadFromFile("Input.xlsx")
 
# Excelワークブックのすべてのワークシートを繰り返し処理する 
for sheet in workbook.Worksheets:
 
# 各ワークシートを個別のPDFファイルとして保存する 
    FileName =  sheet.Name + ".pdf"
    sheet.SaveToPdf(FileName)
workbook.Dispose()
```
![ExcelワークシートからPDFへ.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2811193/f822c67b-c9da-e018-7ddd-1dcb1979aaa8.jpeg)

### 3. Pythonを使用して、指定されたExcelワークシートをPDF形式に変換します：
```python
from spire.xls import *
from spire.xls.common import *
 
# Workbookオブジェクトの作成
workbook = Workbook()
 
# エクセル文書を読み込む
workbook.LoadFromFile("Input.xlsx")
 
# 2枚目のワークシートの入手
sheet = workbook.Worksheets[1]
 
# PageSetupオブジェクトの取得
pageSetup = sheet.PageSetup
 
# ページマージンの設定
pageSetup.TopMargin = 0.3
pageSetup.BottomMargin = 0.3
pageSetup.LeftMargin = 0.3
pageSetup.RightMargin = 0.3
 
# ページサイズの設定
pageSetup.PaperSize = PaperSizeType.PaperA3
 
# 変換時にページに合わせてワークシートを設定する
workbook.ConverterSetting.SheetFitToPage = True
 
# ワークシートをPDFファイルとして保存する
sheet.SaveToPdf("ExcelワークシートからPDFへ.pdf")
workbook.Dispose()
```

* * *
ウォーターマークを削除するには、クリックして無料トライアルライセンスをリクエストすることができます：
https://www.e-iceblue.com/TemLicense.html
モダンCSSまとめ

![水色　シンプル　女性の働き方　note記事見出し画像.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3756285/2a4087cc-c7de-8bc2-2ee0-2d32424c542c.png)

なんだか最近、いや結構前から知らないCSSを見かけるな…トレンドを置いてかれていると感じたため、学習用に最新のモダンCSSをまとめてみます。

## コンテナクエリ

メディアクエリはデバイス画面幅でスタイルを適用するものですが、コンテナクエリは要素のコンテナ幅等に応じてスタイルを適用できます。
適用したい要素にcontainer-typeプロパティを追加し、size、inline-size、normalのいずれかの値を指定します。

:::note info
**値の種類**
size
横軸・縦軸とも対象

inline-size
横軸が対象

normal
デフォルト値。コンテナサイズクエリのクエリコンテナではなく、コンテナスタイルクエリのクエリコンテナとして残る。
:::


<p class="codepen" data-height="300" data-theme-id="light" data-default-tab="html,result" data-slug-hash="yLrXQgZ" data-user="moco2-design" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/moco2-design/pen/yLrXQgZ">
  Untitled</a> by 山﨑恵 (<a href="https://codepen.io/moco2-design">@moco2-design</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>



.containerの横幅を基準として、
３００px以上のコンテナサイズの時に画像を表示、文字は横並び(display:flex)のレイアウト、
それ以下の場合は画像は非表示、文字は縦並びになるように切り分けが出来ました。

コンテナクエリでは、メディアクエリよりも柔軟なレイアウト調整が可能なのかな？という感想です。

:::note warn
**補足**
コンテナクエリはcontainer-typeプロパティを指定した要素の<INS>**子要素**</INS>に効きます。
基準となる親要素（今回の場合.container）のみに値を指定しても効かないので、この点注意です。
:::
テキストが特定の行を超える場合、超過分を ... で表示

テキストの行数を制限して、コンテンツのスペースを効果的に管理することで、ユーザーに対して読みやすいインターフェースを提供することができます。
表示したいテキストの量と利用可能なスペースに応じて、適切な行数での省略表示を活用してみましょう。

## 基本的な使い方

以下のCSSスタイルをテキストを表示している要素に適用することで、３行での省略表示を実現できます。
希望の行数に応じて数字を入れ替えてください。

```css
.text-ellipsis-3lines {
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
  text-overflow: ellipsis;
}
```

このスタイルでは、-webkit-line-clampプロパティを使用して、テキストの表示行数を制限しています。３に設定すると、テキストが３行を超える場合に超過分が省略され、行末に省略記号（...）が表示されます。

## ブラウザの対応状況と注意点

-webkit-line-clampプロパティは、WebKitベースのブラウザ（例えば、SafariやChrome）で広くサポートされています。しかし、すべてのブラウザで対応しているわけではないため、[Can I use...](https://caniuse.com/) などのサイトでブラウザの対応状況を確認しましょう。
SQLAlchemyのexecute()を用いてSQL文を実行したい

## はじめに
- sqlalchemyの難しそうなメソッドを利用せず、簡単にSQL文を実行したかった
- また、sqlalchemyを使っていて、何箇所か詰まるところがあったためご共有

## Code sample
### 1. （任意）DBとコミュニケーションするclassを作る
- 使いまわしたり、何個もオブジェクトを作成する時はclass化しておくと便利です。（ログとかも）
```python
from sqlalchemy import Connection, MetaData, create_engine, text

class DBClass:
    def __init__(self, schema)
    self.schema = schema
    self.engine = create_engine(
    "postgresql://{user}:{password}@{host}:{port}/{database}"
    )

    self.metadata = MetaData(schema=self.schema)
    self.metadata.reflect(bind=self.engine, schema=self.schema)
```
### 2. SQL文を実行する
- `sqlalchemy.text`を利用して、sql文をconnectionに対してexecute()する

```python
sql = f"""
DELETE FROM {schema}.{table_name} WHERE {condition};
"""
dbc = DBClass(schema)
with dbc.engine.begin() as connection:
    results = connection.execute(text(sql))
    logger.info(f"delete {results.rowcount} record.")
```
## sqlalchemyを使っていて詰まったポイント
- postgresから作ったはずのtable一覧が取得できない
- `engine.connect()`に対して`execute()`を実行しても、反映されない
    - 具体的にはSELECT文は通るのにDELETE文は通らなかった
    - `engine.coccect()`　-> `engine.begin()`にすることで治った（理由不明）
        - [公式ドキュメント](https://docs.sqlalchemy.org/en/20/core/connections.html)では`engine.coccect()`　を利用。
        - 理由がわかったら追記します。

## sqlalchemyのオブジェクトがうまく動作しない時、試してみるべきポイント
 - `reflect（）`が実行されているか確認する
     - (memo)engineオブジェクトを利用して何か処理を実行した後、`reflect()`を行わないと反映されない？(branch自体は存在するけれどgit fetchをしないと情報が取得できない、といった感じのものだろうか。)
 - `engine.connect()`でなく`engine.begin()`を利用してみる


## おわりに
- SQLAlchemyの公式docがあるが、読み解くのは難しい...。
高速な検索をおこなうSearchValues<T>クラス

## 参考
この記事は、以下の動画を参考にしています。詳しくは、動画をご覧ください。

https://youtu.be/q0VENoIXWso?si=c9qz79crlL_YJvEh

また、リファレンスも参考にしてください。

https://learn.microsoft.com/ja-jp/dotnet/api/system.buffers.searchvalues-1?view=net-8.0

## SearchValue&lt;T&gt;
- コレクションを引数にして、インスタンスを生成する
- インスタンスに対して`Contains`メソッドを呼び、引数にした値が含まれているかどうかを戻す
- .NET 8では、コレクションのデータ型は`char`または`byte`のみ
- .NET 9では、加えて`string`も可能
- どのように`string`を比較するかは、インスタンスを生成するときに、`StringComparison`を渡して、あらかじめ決める。`Contains`を呼ぶときには`StringComparison`を変更できない

## 訂正（追記）

参考にした動画に、訂正が入りました。

https://youtu.be/K3aByK0Wgh8?si=stGDB3hHDtWQIQR5

この記事も、訂正させていただきます。

### Containsメソッドが本題ではない

`SearchValues<T>.Contains`メソッドは、`SearchValues<T>`を単に`HashSet<T>`として使っているだけである。実際にパフォーマンスは同等である。

### 長大な文字列から部分文字列を探す

長い`string`に、特定の単語が含まれているかを調べたいとする。

`string.Contains`メソッドを使うと、次のようになる。

```C#
string longText = new HttpClient()
    .GetStringAsync("https://www.gutenberg.org/cache/epub/100/pg100.txt")
    .GetAwaiter()
    .GetResult();
var targetWords = ["target", "words"];

var found = targetWords.Any(x => longText.Contains(x, StringComparison.OrdinalIgnoreCase);
// foundがtrueなら、targetWordsのいずれかを見つけた
```

`SearchValues<string>`を引数にする`ContainsAny`拡張メソッドを使うと、以下のように記述できる。

```C#
ReadOnlySpan<char> longText = new HttpClient()
    .GetStringAsync("https://www.gutenberg.org/cache/epub/100/pg100.txt")
    .GetAwaiter()
    .GetResult();
var targetWords = SearchValues.Create(["target", "words"],
                                      StringComparison.OrdinalIgnoreCase);
var found = longText.ContainsAny(targetWords);
// foundがtrueなら、targetWordsのいずれかを見つけた
```

手元の実行環境では、後者は前者に比べて約半分の実行時間になった。

### 文字列に対してSearchValues&lt;string&gt;を引数にして呼び出せる拡張メソッド
以下の拡張メソッドが、`System.MemoryExtensions`クラスで定義されている。（.NET 9 Preview 2時点）

- `ContainsAny`
- `IndexOfAny`

いずれのメソッドも、第1引数は`Span<char>`または`ReadOnlySpan<char>`、第2引数は`SearchValue<string>`である。
XcodeのシミュレーターだとAPIの実行結果が古いままの場合の対処法

## 起きたこと
URLRequestを使ってAPIを叩いて取得結果を使って色々する処理があった。

とあるAPIを呼んでいてそのAPIが作業していた日にレスポンスが変わることが確定となっていた。
しかし、シミュレーターで実行したらレスポンスが古いままとなっていて、実機だと正常に最新となっていた。


# 解決方法
- 他のシミュレーターを使ったり作り直したらいける。
※キャッシュが溜まってしまうようなので、キャッシュクリア関連のコマンドを試したが変わらなかったので、、、ここ分かったら追記する。
Google Colaboratory(Python実行環境)の初期設定

Google Colaboratoryの初期設定を残します。

# インストールする
## Google Driveを表示する

## 新規をクリックする
![0.新規(選択前).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106311/ddd1f572-5d5c-fd7d-7adb-3f2e2b610d0a.png)

## アプリを追加をクリックする
- その他 > アプリを追加

![1.新規.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106311/436ba7e4-48e8-1786-3bd9-e76929951078.png)

## アプリ検索画面で検索する
- Colaboratoryと入力する
- Colaboratoryをクリックする
![2.検索.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106311/2e1d987f-9075-e102-5704-711ec036aaf9.png)

## インストールをクリックする
![3.検索-colab.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106311/55059db0-b594-bf98-ea43-5156f4dfb05d.png)

## インストール権限を付与する

![4.colob-権限.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106311/3e126176-d497-2ea4-fa53-0f8f4608c658.png)

![5.colab-権限アカウント選択.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106311/313117a1-33b3-f9fc-b0db-b2d42440029d.png)
![6.colab-権限アカウントログイン.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106311/fe32261d-7f34-f1c7-54b8-4a3ac06e53ca.png)

## 関連付けを選択する
![7.colab-関連付け.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106311/b1bb6adc-8898-f346-932c-4189c8a58e35.png)

## インストールが完了する
- 完了をクリックする
![8.colab-インストール完了.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106311/a65db970-9088-3835-2695-4301c5ef6dc5.png)

# はじめてのPythonコードを実行する

## 新規をクリックする
![0.新規(選択前).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106311/ddd1f572-5d5c-fd7d-7adb-3f2e2b610d0a.png)

## Google Colaboratoryをクリックする
- その他 > Google Colaboratory
![11.新規(インストール後).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106311/494553f3-9200-32aa-124c-047ca47f4ced.png)

## Google Colaboratoryファイルが生成される
![12.colab初期.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106311/abe8a9a0-9ac1-ed9c-361b-8294004b0b40.png)
- ファイル名をMyFirstPython.ipynbに変更する
- ファイル名を変更するとGoogle Driveに即時反映される
![12-1.colab名前変更.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106311/8dffef67-4bf8-e709-acd3-bd244a60bb41.png)


## Hello World!を入力し、実行ボタンをクリックする
![13.coloba-helloworld1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106311/19667c14-d2b2-ef7e-4107-b96a1e80ea10.png)


```python:MyfirstPython.py
print('Hello World!')
```


## コードが実行される
![14.coloba-helloworld2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106311/941e2f5a-c087-184c-cb32-259d11ecd472.png)

- 始めてのPythonコードが実行できました
【AmazonSQS】障害時DLQに転送されたキューをSQSに再送したい(DLQ再処理)



![AmazonSQS 障害時DLQに転送されたキューをSQSに再送したい(DLQ再処理).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3754524/712e2579-1b08-8d82-ba3f-5a5c423741b6.png)

## 本記事で実現できること
障害時にDLQに転送されたキューを、オリジナルのSQSに再送する

## 前提
- AWSマネコンはログイン済み
- 2024.3.28 時点でのコンソールのUIになります
- 障害時などDLQに転送されたキューが存在している

## 簡単な解説
全部で7フェーズ

①ホーム画面で、画面上部検索欄に[**SQS**]と入力。
　出てくるサービスの中から[**SQS**]をクリック

![AmazonSQS 障害時DLQに転送されたキューをSQSに再送したい(DLQ再処理) (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3754524/6ef1189b-9757-cde3-52ca-09dfe381c609.png)

②再送したいDLQの名前部分をクリックする。
![AmazonSQS 障害時DLQに転送されたキューをSQSに再送したい(DLQ再処理) (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3754524/8ed8d12f-3088-6860-039e-7cd35d927be4.png)

③[**DLQ再処理の開始**]をクリック。
![AmazonSQS 障害時DLQに転送されたキューをSQSに再送したい(DLQ再処理) (3).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3754524/ab9b7767-62f7-c58e-f9c0-610a3816235b.png)

④メッセージを元のキューへ戻すので
 - **メッセージ送信先　　　 →　「再処理のためソースキューに入れる(デフォルト)」**
 - **速度コントロール設定　→　「システムは最適化されました(デフォルト)」**
 を選択。
![AmazonSQS 障害時DLQに転送されたキューをSQSに再送したい(DLQ再処理) (4).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3754524/8aa91d58-a36d-0de8-fe12-9a2641df15d6.png)

⑤
DLQのメッセージのポーリングでは下記3点を対応する。
- [**メッセージをポーリング**]をクリックして受信を行う。
- メッセージを確認。再処理可能な場合は(2)の部分に出力されるのでチェックを入れる。
※再処理可能なメッセージがない場合はメッセージが出力されない。

- [**DLQ再処理**]をクリックして再処理を開始する。
![AmazonSQS 障害時DLQに転送されたキューをSQSに再送したい(DLQ再処理) (5).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3754524/bf356663-c6df-0ff4-f651-65c16cb095e1.png)

⑥再処理の進捗画面に遷移して、進捗が表示される。
 ステータスが[進行中]になっているので[**正常に完了しました**]に遷移するまで待機。
![AmazonSQS 障害時DLQに転送されたキューをSQSに再送したい(DLQ再処理) (6).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3754524/11526120-f342-273c-ebfa-b7932b70892b.png)

⑦ステータスが[**正常に完了しました**]になったら、ソースキューへのメッセージ送信が完了。
![AmazonSQS 障害時DLQに転送されたキューをSQSに再送したい(DLQ再処理) (7).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3754524/87a644bd-7dcf-5cca-d284-0c27147dca55.png)


## まとめ
本稿が、DLQ再処理を行いたい方の参考になれば嬉しいです。

ITエンジニア向け、AWS資格取得を目指す方向けに個人ブログで記事も投稿していますので、
合わせて読んでもらえると嬉しいです。
[ことなの学校(個人ブログ)](https://kotona-school.com)

更によりレベル感の高そうなAWS関連の発信はZennの方で行います。
こちらももしよければフォロー、ご確認いただけると嬉しいです。
[Zenn個人アカウント](https://zenn.dev/tomo_itbizblog)

Twitterでも役立つ情報を発信しますのでフォローしてもらえると嬉しいです 
→ [@tomo_ITBizBlog](https://twitter.com/tomo_ITBizBlog)
ASMディレクトリごとの使用率などを確認

まず、ASMのインスタンス名を確認

以下のコマンドを実行

ps -ef | grep asm_

実行すると、こんなのが出る。
[grid@ptvm10 ~]$ ps -ef|grep asm_
grid 19176 1 0 3 月 30 ? 00:00:05 asm_pmon_+ASM1
grid 19181 1 0 3 月 30 ? 00:00:04 asm_clmn_+ASM1
grid 19185 1 0 3 月 30 ? 00:00:18 asm_psp0_+ASM1
grid 19189 1 1 3 月 30 ? 00:28:29 asm_vktm_+ASM1

この場合、インスタンス名は　+ASM1　になる。

export ORACLE_SID=+ASM1

sqlplus / as sysasm

で、タイトルの情報を得るためには以下のSQLを実行。

以下のページを参照しました。
https://www.fuku.tokyo/2022/02/asmfile/
例によって、「ラーメン屋になりたいSEのブログ」です。

set linesize 200
set pagesize 100
col file_type format a20
col path format a100
col "USED%" for 990.9
define dirlv=2
select
  file_type,
  count(*) files,
  round(sum(space)/1024/1024) mbytes,
  round(sum(space)/1024/1024/dgmsize*100, 1) "USED%",
  path
from
  ( select
      concat('+'||gname, replace(sys_connect_by_path(case when level < &dirlv then '/'||aname else '' end, '|'), '|', null)) path,
      file_type,
      space,
      gname,
      dgmsize
    from
      ( select b.name gname, a.name aname,
          a.reference_index rindex, a.parent_index pindex,
          c.type file_type, c.space,
          a.system_created, a.alias_directory,
          b.total_mb dgmsize
        from v$asm_alias a, v$asm_diskgroup b, v$asm_file c
        where a.group_number = b.group_number
          and a.group_number = c.group_number(+)
          and a.file_number = c.file_number(+)
          and a.file_incarnation = c.incarnation(+)
      )
    where
      connect_by_isleaf = 1 and alias_directory = 'N' -- 経路ディレクトリと空ディレクトリを省く
      and not (system_created = 'N' and alias_directory = 'N') -- エイリアスファイルを省く
    start with (mod(pindex, power(2, 24))) = 0
    connect by prior rindex = pindex
  )
group by file_type, path, gname, dgmsize
order by gname, mbytes desc
;

linesizeとかカラムの表示サイズなどを調整する必要があるかも。
Xstate で基本的なステートマシンを作成する

状態とその遷移が予め大体決まっている場合、Xstate のEditor を利用すると視覚的にも分かりやすくステートマシンが作れます。今回はEditor の使い方と、各状態と遷移、Context 、Action 、invoke について記載したいと思います。
# xstate Editor の使い方
## 状態の作成と遷移方法
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1781492/6cdd1760-f2d1-bbe1-5622-99f3ae88757b.png)
firstState からNEXT が呼ばれた場合はsecondState へ、CANCEL が呼ばれた場合はthirdState に遷移します。

## Action
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1781492/5ffe46fe-ba22-5bd1-e287-deb142baee97.png)
ここでは遷移にAction がついています。Action は状態につけることもできます。この場合は、secontState 状態に入ったときに指定のsetParameter が実行されます。Action はただ実行されるものなので、分岐等はありません。Context にデータをセットする動作や、クリーンアップ動作で利用しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1781492/5d032d82-430e-4d6c-e31e-152ecbae7349.png)

## Invoke
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1781492/9d16d738-c558-792f-8f00-eb6b8b8be73b.png)
invoke は状態につけることができます。invoke ではreject とresolve で渡す先を選び、done の場合とerror の場合で異なる遷移先を指定することができます。バリデーションチェックや、エラー処理が必要な動作はinvoke を使っていました。

# コード実装
Xstate のEditor からコードに落とすことができます。今回は一例として少しコードを紹介します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1781492/7e9a8933-e9e8-9687-d8a6-972303ab54d8.png)

今回のこのコードでは、Editor からコードを起こすと以下のようになります。Action やService は別のところに記載します。Context はparameter のみを持つようにしています。

```
import { createMachine } from "xstate";

interface machineContext {
  parameter: boolean | undefined,
}

const machine = createMachine<machineContext>({
  context: {
    parameter: undefined,
  },
  id: "stateMachine",
  initial: "firstState",
  states: {
    firstState: {
      on: {
        NEXT: {
          target: "secondState",
        },
        CANCEL: {
          target: "thirdState",
          actions: {
            type: "cleanUp",
          },
        },
      },
    },
    secondState: {
      entry: {
        type: "setParameter",
      },
    },
    thirdState: {
      invoke: {
        onDone: {
          target: "success",
        },
        onError: {
          target: "error",
        },
        src: "ValidationCheck",
      },
    },
    success: {},
    error: {},
  },
});
```

コンポーネント内で使う際は、UseMachine を利用します。

```
const [ state, send ] = useMachine(machine, {
    actions: {
      cleanUp: (_, event) => {
     　 // 実装
        });
      },
      setPrameter: assign({ parameter: (_context, event) => event.data.parameter }),
    },
    services: {
      ValidationCheck: (context, _event) => {
        return new Promise((resolve, reject) => {
        // resolve ならDone 遷移、reject ならError 遷移
          }
        });
      },
    },
  });
```

ここでAction とInvoke のService を設定します。遷移を呼ぶ際は以下のように書きます。

```
send({ type: 'NEXT', data: { parameter } })
```

parameterの中には入れたいデータが入ります。これて、NEXT が呼ばれ、setParameter でContext に値がセットされます。Service の中でContext に値を渡すこともできます。resolve (あるいはreject )で以下のように記載します。

```
resolve({ data: parameter });
```
Mackerel の OpenTelemetry（ラベル付きメトリック）をオンプレサーバで試した備忘録

# 動機

今更ながら Mackerel で OpenTelemetry（ラベル付きメトリック）を試したくなったが、探しても Docker + ECR とか K8S とか最近流行りの情報ばかり出てきて、現在の社内サーバの状況には合わなかったため、備忘録としてまず Nginx のラベル付きメトリックを投稿できるところまで書いておく。

# サーバ情報

- OS : Rocky Linux 8
    - ~~まぁ使い始めてしまったのでしょうがない~~
- Nginx : 1.22.1

# Nginx の準備

適当に stub_status を出せる location を用意。
（OpenTelemetry の nginx receiver が http_stub_status を元に投稿するらしいので）

```conf:/etc/nginx/conf.d/status.conf
server {
    listen 80;
    server_name localhost;

    location = /status {
        stub_status;
    }
}
```

```bash
# curl http://localhost/status
Active connections: 2
server accepts handled requests
 70704 70704 70828
Reading: 0 Writing: 1 Waiting: 1
```

# OpenTelemetry Collector Contrib のインストール

ここがあまり情報出てこなくて色々つまづいた。
[OpenTelemetry 公式に RPM installation の項目](https://opentelemetry.io/docs/collector/installation/) もあるが、ここでインストールできる `otelcol` では nginx の receiver が入っていないため使えない。
使うのは OpenTelemetry Collector Contrib のほう。
https://github.com/open-telemetry/opentelemetry-collector-releases

```
wget https://github.com/open-telemetry/opentelemetry-collector-releases/releases/download/v0.96.0/otelcol-contrib_0.96.0_linux_amd64.rpm
yum install ./otelcol-contrib_0.96.0_linux_amd64.rpm
```

設定ファイルなどは `/etc/otelcol-contrib/` に入る。

```bash
# ls -l /etc/otelcol-contrib/
合計 12
-rw-r--r-- 1 root root  424  3月 26 14:40 config.yaml
-rw-r--r-- 1 root root 1461  3月  5 19:48 config.yaml.bk
-rw-r--r-- 1 root root  246  3月  5 19:48 otelcol-contrib.conf
```


# Mackerel 向けに設定して起動

ここまで来たらほぼ [Mackerel のチュートリアル](https://mackerel.io/ja/blog/entry/using-open-telemetry-labeled-metrics-with-mackerel) 通りに進めるだけ。

```yaml:/etc/otelcol-contrib/config.yaml
receivers:
  nginx:
    endpoint: "http://localhost:80/status"
    collection_interval: 10s

processors:
  batch:
    timeout: 1m

exporters:
  otlp/mackerel:
    endpoint: otlp.mackerelio.com:4317
    compression: gzip
    headers:
      Mackerel-Api-Key: "insert your Mackerel API Key (write)"

service:
  pipelines:
    metrics:
      receivers: [nginx]
      processors: [batch]
      exporters: [otlp/mackerel]
```

設定ファイルの解説についてはチュートリアルに詳しく書いてあるのでそちらを。
ここにある `receiver.nginx` が Contrib じゃないと入ってないので動かず、しばらく悩んでしまった。
API Key はベタ書きにしているが、OS 環境変数に入れるなどしたほうがいいかも知れない。

設定したら再起動。

```
systemctl restart otelcol-contrib.service
```


# 確認

あとはチュートリアルの通り、カスタムダッシュボードを作成してグラフを作るだけ。

![スクリーンショット 2024-03-26 15.11.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/88428/bdb8d745-a78a-0d5b-d7df-bc58b1a5a565.png)

http_stub_status で取れる情報はあまり多くもないので、OpenTelemetry 用の module を入れたりすればより多くの情報が可視化できるようになると思われる。


# 感想

今まで使ってきた Mackerel にそのまま PromQL で出せるグラフを投げつけられるのはやはり便利そう。
既存の mackerel-agent や plugin によるグラフ資産とも競合してしまう部分ではあるので、今後のアップデートに合わせて移行・共存していければいいなぁと思う。
~~特に課金体系が気になる・・・うちはホストが多めなのでホストメトリックとしてカウントしてもらえるとありがたい:innocent:~~


# 終わりに

ねこじゃらしでは人材募集中です。
https://www.green-japan.com/company/2706
Firebaseのデプロイの裏で行われていること

# 初めに
今回supabaseとReactで構築した学習記録アプリを、webアプリとしてFirebaseに公開しました。
公開の過程でターミナル上に`firebase deploy`を入力しても、画面が表示されないと言う事例があったので報告します。

#　問題
Firebaseのプロジェクトを作成して、CLIインストール・Firebaseログイン・Firebase初期化まで完了した時点で`forebase deploy`をターミナル上に入力しました。
手順としてはこれで問題ないのですが、ターミナル上に表示されたURLをクリックしても「Firebase Hosting Setup Complete」の文字しか表示されません。

# 解決策
解決策というほどでもありませんが、今回は時間が経てば表示されるようになりました。
原因として考えられることはデプロイメントの方式が関係している可能性がありました。

# そもそもデプロイメント（デプロイ）とは？
デプロイメントについて記載されてる記事がありましたので紹介します。
>「構築したプログラムをユーザーがアクセスできるような本番環境に移し、意図した通りに動作する状態」にすること
だそうです！

そしてこのデプロイメントについては4種類あります（僕が調べた感じだとおそらく４種類）
<dl>
<dt>ブルーグリーンデプロイメント</dt>
<dd>旧バージョンであるブルー環境と新バージョンであるグリーン環境の2つのサーバーを用意し、ロードバランサーなどで切り替えができるようにする方式。グリーン環境を構築中でもブルー環境を起動することができて、グリーン環境の正常動作が確認できたらブルーからグリーンに切り替える。万が一切り替え後にグリーン環境で不具合が起こってもブルー環境に戻すことが可能</dd>

<dt>イミュータブルデプロイメント</dt>
<dd>ブルーグリーンデプロイメントと似ているが、異なる点は新バージョンへ移行後は旧バージョンを残さないこと。サーバー代の節約になるが旧バージョンに戻すことはできない。</dd>

<dt>シンボリックリンクデプロイメント</dt>
<dd>上記の2つの方式とは異なりこの方式はサーバーを1つしか用いないことが特徴。サーバーが一つで済むため運用コストは低くなるメリットがあるが、サーバーの再起動が必要になったり、サーバーエラーが起こった際に影響を受けることがある。</dd>

<dt>ローリングデプロイメント</dt>
<dd>ローリングデプロイとは、アプリケーションが実行されているインフラを完全に置き換えることによって、古いバージョンのアプリケーションを新しいバージョンに順次置き換えることでデプロイを行う方法。ローリングデプロイは上記で紹介したブルーグリーンデプロイと比べ、高速に実行されますが、古いバージョンと新しいバージョンのサーバーが混在し、分離することができないため、リスクが増大し、デプロイが上手くいかなかった際のロールバックプロセスが複雑になることがあります。</dd>
</dl>

# 今回の表示されなかったことへの考察
おそらくfirebaseへのデプロイをローリングデプロイメント方式で行なっているため、デプロイした直後は順次置き換えている途中だったのかなと思っています。
旧バージョンと新バージョンが混在してエラーが生じ、画面が表示されなかったと考えられます。
[Go]環境変数 まとめ

実務のプロダクションコードで、普段意識してなかった環境変数周りの処理を追ったときに前提知識が不足しすぎてて、とても苦労したのでまとめておく

# osパッケージ利用

```sample.go
package main

import (
	"fmt"
	"os"
)

func main() {
	// 環境変数のセット
	os.Setenv("APP_ENV", "prod")
	
	// 環境変数の取得
	appEnv := os.Getenv("APP_ENV")
	fmt.Printf("appEnv: %v\n", appEnv)
}
```
[PlayGround](https://go.dev/play/p/yLn4t9hNPgx)

# [envconfig](https://github.com/kelseyhightower/envconfig)パッケージ利用
「環境変数名を列挙した構造体を渡すことで、各フィールドに環境変数を一気に読み込む」
機能を提供してくれるパッケージ。2024/11/12時点で、Star5.1kと人気がある(ただし最終コミットは2年前になっている)。
READMEに記述されている内容や、実際の挙動を確認した結果から察するに、以下の縛りで利用することを想定している模様。
- 環境変数名: 大文字スネークケース
- 環境変数値を保存する構造体のフィールド名:
    - パスカルケース(アッパーキャメルケース)
    - 環境変数が複数単語からなる場合: `split_words:"true"` タグを付与 (タグを付与しない場合、例えばXXX_YYYという環境変数の場合、フィールド名をXxxYyyにしたとしても、環境変数XXXYYYを探すため読み取れない)
    - 環境変数に数値がまざる場合: `envconfig:"<環境変数名(小文字スネークケース)>"` タグを付与 (タグを付与しない場合、例えばXXX_YYY_1という環境変数の場合、フィールドを XxxYyy `split_words:"true` にしたとしても、環境変数XXX_YYY1を探すため読み取れない)

また、環境変数値を保存する構造体には、想定する環境変数自体が見つからなかった場合に、デフォルト値をセットする`default`、エラーにする`required`といったタグが指定できる。
```sample.go
package main

import (
	"fmt"
	"log"
	"os"

	"github.com/kelseyhightower/envconfig"
)

func main() {
	// 環境変数をセット
	os.Setenv("APP_ENV", "prod")
	os.Setenv("APP_SERVER_NAME_1", "prod_server_1")

	// 環境変数値を保存する構造体
	type environmentalVariable struct {
		AppEnv         string `split_words:"true" required:"true"`                    // 環境変数 APP_ENV に対応
		AppServerName1 string `envconfig:"app_server_name_1" default:"test_server_1"` // 環境変数 APP_SERVER_NAME_1 に対応
	}
	var envVar environmentalVariable

	// envconfigを使った環境変数の取得
	if err := envconfig.Process("", &envVar); err != nil {
		log.Fatalf("envconfig.Process() failed. (err:%v)", err)
	}
	fmt.Printf("envVar: %+v\n", envVar)
}
```
[PlayGround](https://go.dev/play/p/5zdn5-Vtw_4)


# [env](https://github.com/caarlos0/env)パッケージ利用
こちらも envconfig とよく似たもので、「環境変数名を列挙した構造体を渡すことで、各フィールドに環境変数を一気に読み込む」機能を提供してくれるパッケージ。2024/11/12 時点で Star4.9kと人気がある。最終コミットも3週間前とメンテは続いている模様。
クロスプレイ(GeyserMC)サーバーの立て方

:::note alert
新記事を閲覧してください

未公開

:::

今回は、以前紹介したサーバーをクロスプレイできるようにするプラグイン(GeyserMC)を紹介していきます

## この記事を読む前に
この記事を読む前に前書いたサーバーの作り方をご参照ください
https://qiita.com/ikatakoch/items/2f744284df84ddb05cde

## クロスプレイ？
まずはクロスプレイについて解説していきます。
クロスプレイのことを知っている方は「ダウンロード」まで飛ばしてください。

クロスプレイとは、異なる機種間で通信を行い、協力や対戦プレイを行う機能のことです。
マインクラフトでは、「Java版」「統合版」の二つに分かれているので、Java版と統合版でマルチプレイができるようにする機能のことです。

## ダウンロード...?
ダウンロードしたいところですが、プラグインを使用するためにSpigotMCまたはPaperMCをインストールしましょう。
spigotは[spigotmc.org](https://www.spigotmc.org)、paperは[papermc.io](https://papermc.io)
ここからは、spigotの説明に入ります。
paperをインストールする方は「PaperMC」まで飛ばしてください

## spigot

サイトを開いたら、人間かどうかを確かめる画面が出ます。
認証をし、英文がいろいろでてきたら、下の方にある2個目の「continue」を押します。(画像は翻訳済み)
下の画像で言うWindows Defenderの偽陽性(Windows Defender False Positives)の下にあるスピゴット&バンジーコード1.20.4の「continue」を押してください

![スクリーンショット 2024-03-26 14.11.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3611904/058a3ebe-4457-6dcd-b937-8c38c4f5f2cf.png)

開いたら赤線が引かれている(画像で)「this link」をクリックします。
![スクリーンショット 2024-03-26 14.18.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3611904/2d94f996-ddc9-e5d3-cfa2-51211d50a18f.png)
クリックすると、ファイルがダウンロードされます
ここからは,以下のサイトを参考にしながら作業を進めてください。
(以前書いた記事です)

https://qiita.com/ikatakoch/items/2f744284df84ddb05cde#準備

サーバーの建て方の記事なので、すでに見ている方はみなくてOKです。
前回と同じ、サーバーを建てる作業をしてください

ここまで読んだ方は、「いよいよダウンロード」までとばしてください

## paper
サイトを開き、「downloads」をクリックして「paper」をクリックし、青いボタンを押すとダウンロードできます。

## いよいよダウンロード
クロスプレイに使うプラグインをダウンロードしていきます
まず、[geysermc.org](https://geysermc.org)にアクセスします
![スクリーンショット 2024-03-26 13.05.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3611904/8e5a2af4-4e29-ead2-e81b-164f79f49656.png)
右上の「download」を押します。
「Spigot/Paper」を選択します

そして、サーバのファイルの中に「plugins」というフォルダがあるのでそこにぶち込みます☆

## 動作確認
https://qiita.com/ikatakoch/items/2f744284df84ddb05cde#起動
と
https://qiita.com/ikatakoch/items/2f744284df84ddb05cde#接続
を参考にして進めてください。

## スイッチで参加
早速スイッチ(統合版)で参加したいところですが、近日中に他コンピューターから参加する方法を紹介する記事を書くため、もう少しお待ちください

## 終わり
今回はクロスプレイサーバーの立て方を説明しました
語彙力がないので、わかりにくい場合は、コメントで教えてください。
できる限り対応させていただきます。
不具合が起きた場合の記事は、また作ろうと思いますので、待っていてください。
その他、ご用件、ご要望、リクエストがあればコメントにお願いします。
ちなみにyoutubeもやっていますので登録よろしくお願いします。(Xも)

youtube⇩
https://www.youtube.com/channel/UCvPHfXSqUPe5vD_ZBFM16TA
X⇩
https://x.com/ikatakoch_x
意見箱⇩
https://forms.gle/UdQWtm7bUWkSmN6D7

次回⇩

https://qiita.com/drafts/d9418d83a206a63669df/edit



## 引用

wikipedia

## 注意
この記事は2024年3月26日(火)に書かれたものです。
1年経過した場合、この記事の情報は正しくないものと思ってください
Docker キャッシュの削除

## はじめに
dockerを使用しているとキャッシュやimageの容量が逼迫してbuildができなくなることがある
消す系のコマンドをまとめておく

# コマンド
```shell
# 一括コンテナ停止
docker stop $(docker ps -q)

# 一括コンテナ削除
docker rm $(docker ps -q -a)

# 一括イメージ削除
docker rmi $(docker images -q)

# volume一括削除
docker volume rm $(docker volume ls -qf dangling=true)

# キャッシュの削除
docker builder prune
```

```shell
# キャッシュの量を確認できる
# docker builder prune中に別windowで適宜確認するとどんどん減っているのがわかる
docker system df
```
k6逆引きメモ

必要に迫られたk6の逆引きメモです

## 概要

[k6](https://k6.io)はREST API等の負荷テストを行えるツールになります

## Docker Containerでの実行

`Docker Container`→`ホスト`間にてテストを行います

### k6テストスクリプト

```javascript
import http from 'k6/http';
import { sleep } from 'k6';
import { check } from 'k6';

export let options = {
    vus: 10,
    iterations: 1000
};

export default function () {
    let res8 = http.get('http://host.docker.internal:80/api/v1/test', {timeout: '1s'});
    check(res8, {
        'status was 200': (r) => r.status == 200
    });
    sleep(1);
}

```

### 実行

```bash
docker run --rm -v ./test.js:/test.js grafana/k6 run /test.js
```

### 実行結果
```text
running (02m46.0s), 10/10 VUs, 1605 complete and 0 interrupted iterations
default   [  80% ] 10 VUs  02m46.0s/10m0s  1605/2000 shared iters

     ✗ status was 200
      ↳  92% — ✓ 1490 / ✗ 125

     checks.........................: 92.26% ✓ 1490     ✗ 125
     data_received..................: 5.3 MB 32 kB/s
     data_sent......................: 240 kB 1.4 kB/s
     http_req_blocked...............: avg=5.86ms   min=0s     med=3.18ms  max=109.98ms p(90)=9.88ms   p(95)=17.16ms
     http_req_connecting............: avg=5.58ms   min=0s     med=3ms     max=105.06ms p(90)=9.6ms    p(95)=16.96ms
     http_req_duration..............: avg=15.66ms  min=0s     med=10.98ms max=150.46ms p(90)=25.39ms  p(95)=39.93ms
       { expected_response:true }...: avg=15.7ms   min=7.86ms med=11.01ms max=150.46ms p(90)=25.27ms  p(95)=39.72ms
     http_req_failed................: 7.73%  ✓ 125      ✗ 1490
     http_req_receiving.............: avg=543.98µs min=0s     med=354.1µs max=8.47ms   p(90)=1.1ms    p(95)=1.61ms
     http_req_sending...............: avg=199.22µs min=0s     med=148.6µs max=61.16ms  p(90)=226.46µs p(95)=252.4µs
     http_req_tls_handshaking.......: avg=0s       min=0s     med=0s      max=0s       p(90)=0s       p(95)=0s
     http_req_waiting...............: avg=14.91ms  min=0s     med=10.41ms max=150.02ms p(90)=24.13ms  p(95)=39.5ms
     http_reqs......................: 1615   9.722711/s
     iteration_duration.............: avg=1.03s    min=1.01s  med=1.01s   max=2s       p(90)=1.03s    p(95)=1.06s
     iterations.....................: 1605   9.662508/s
     vus............................: 10     min=10     max=10
     vus_max........................: 10     min=10     max=10


running (02m46.1s), 00/10 VUs, 1605 complete and 10 interrupted iterations
default ✗ [  80% ] 10 VUs  02m46.1s/10m0s  1607/2000 shared iters
time="2099-01-01T01:02:34Z" level=error msg="test run was aborted because k6 received a 'interrupt' signal"
```
Salesforce認定アドミニストレーター過去問+時々解説　Q91 ~ Q100

## Q91. 顧客が解決策を自分で見つけることができるサービスは次のうちどれですか？

A コールセンター
B Eメール
C チャット
D カスタマーポータル

<details><summary>解答</summary>
D

解説: カスタマーポータルとは, 顧客自身がマイページにアクセスし, データ登録やケース作成, ナレッジ記事の参照が行えるコミュニティとなる. ナレッジ記事を参考にすることで顧客自身での解決策の発見につながるので, カスタマーポータルが解答となる.
</details>

## Q92. ユーザーグループにカスタムアプリケーションへのアクセス権を制限するためには, システム管理者はどの機能を利用すればよいですか？

A 共有ルール
B プロファイル
C Web タブ
D ページレイアウト

<details><summary>解答</summary>
B

解説: カスタムアプリケーションのアクセス制限を設定するには, Lightningアプリケーションビルダーのユーザープロファイルから, プロファイル（ユーザーグループ単位）でアクセスを制御する.
</details>

## Q93. データローダに該当する説明を選択せよ.

A カスタムオブジェクトを読み込めません
B ロード後にエラーレポートを生成します
C カスタムオブジェクトを含むすべてのオブジェクトをロードできます
D レコードを重複排除して挿入します
E salesforce.comアプリケーションとともにインストールされています

<details><summary>解答</summary>
B, C

解説: カスタムオブジェクトを含むすべてのオブジェクトをロードできるのでAは非選択, レコードの重複削除はしてくれずエラーログとして出力するのでDも非選択, またデータローダはインストールが必要なのでEも非選択.
</details>

## Q94. SalesforceレコードIDについて, 正しく表現しているのは次のうちどれ？

A 本番環境および設定のみサンドボックスで同じ
B 本番環境およびフルコピーサンドボックスで同じ
C 環境が異なれば、レコードIDも常に異なる
D 本番環境および開発者サンドボックスで同じ

<details><summary>解答</summary>
B

解説: URLに含まれるレコードIDとは, レコードを登録するとSalesforceがレコードへ自動的にIDを割り振る. このIDは, 本番環境の前レコードをコピーして作るFull Sandboxで同一IDとなる.
</details>

## Q95. カスタムオブジェクトは標準オブジェクトの主にできますか？

<details><summary>details</summary>
いいえ

解説: 標準オブジェクトは, カスタムオブジェクトの従側になることはできない.
</details>

## Q96. 外部IDとして使用できる項目タイプはどれ？

A テキスト項目
B URL項目
C 数式
D 数値
E メールアドレス

<details><summary>解答</summary>
A, D, E

解説: 
</details>

## Q97. Salesforceのユーザーレコードに割り当てることができる機能ライセンスはどれですか？ 2つ選べ.

A Service Cloudユーザ
B 商談ユーザ
C コンソールユーザ
D ナレッジユーザ

<details><summary>解答</summary>
A, D

解説: 公式ヘルプ参照
https://help.salesforce.com/s/articleView?id=sf.users_feature_licenses_available.htm&type=5
</details>

## Q98. 管理者は, １２ヶ月以上経過していて, ステータスがnewのカスタムオブジェクトから全てのレコードを削除するように要求している. 管理者はこの要求を尊重するために何を使用する必要がある？

A データローダー
B 一括削除
C データインポートウィザード
D リストからの一括編集

<details><summary>解答</summary>
A

解説: 一括削除は, カスタムオブジェクトではサポートされていない. また, インポートウィザードはレコードの追加と更新だけで, 削除を行うことはできない.
</details>

## Q99. レポートに下記の条件が設定されている.
1) ロール=営業部
2) レポート種別=商談結果
3) 所有者=システム管理者
レポートに表示するデータを「営業部ロールのレポート種別が商談結果, もしくはシステム管理者が所有者のデータ」で絞り込む場合, レポートの検索条件ロジックに何を設定する必要がありますか?

A (1 OR 2 OR 3)
B (1 OR 2) AND 3
C (1 AND 2) OR 3
D 1 AND (2 OR 3)

<details><summary>解答</summary>
C
</details>

## Q100. Chatterの機能に該当するものを3つ選択せよ.

A ブックマーク
B フィード
C メモ
D イベント
E 推奨事項(おすすめ)

<details><summary>解答</summary>
A, B, E

解説: chatterではブックマークしたレコードをフィード機能から確認でき, 推奨事項の表示機能もある.
</details>

## Q101~Q110
https://qiita.com/taiga-shiokawa/items/fe50c1133a3f9be8673c
【Bash】headコマンドによってPIPESTATUS 141が発生する

# 問題
以下のbashスクリプトを実行すると、

```bash
seq 1 100000 | head ; echo ${PIPESTATUS[@]}
```

次のように出力される。
（全体としての終了ステータスは0です。）

```bash
1
2
3
4
5
6
7
8
9
10
141 0
```

# 原因
`head` が必要とする行数を読み込んだ後に終了するため、`seq` からの追加の出力がパイプを通じて `head` に送信されることなく破棄されます。
これにより `seq` コマンドは SIGPIPE シグナルを受信し、結果として `PIPESTATUS[0]` は `141` (128 + SIGPIPE のシグナル番号13) を返します。

引数なしの `head` が必要とする行数は10行ですが、10行より多少多いだけなら `seq` による出力が間に合って `PIPESTATUS[0]` は `0` になります。
環境によりますが、1000行くらいなら `PIPESTATUS[0]` は `0` になります。

```bash
# PIPESTATUS[0] はおそらく 0 になる。
seq 1 1000 | head ; echo ${PIPESTATUS[@]}
```

`dd` で `/dev/null` へ捨てることで、`PIPESTATUS[0]` を `0` にできます。
（最後まで実行するため、実行時間が長くかかります。）

```bash
# 実行時間はかかるが、 PIPESTATUS[0] は 0 になる。
seq 1 100000 | (head; dd status=none of=/dev/null) ; echo ${PIPESTATUS[@]}
```

# 参考文献
- https://github.com/jqlang/jq/issues/1017
- https://chat.openai.com/share/e9ac5c19-e685-4d44-b54e-1684a4f91233
ORA-19809エラーと高速リカバリ領域のファイル削除

## はじめに
開発環境でテーブルの数百万件データの更新・削除処理をかけたところ、DBサーバが停止し再起動できない状況に陥った。
原因究明と解決方法を備忘としてまとめておく。
OSはWindows Server2019、DBはOracle Database 19cを前提として記載する。

## ログを見る
DBサーバの障害発生時はalertログを見る。
alertログのディレクトリはデフォルトでは以下の通り。
```
$ORACLE_BASE/diag/rdbms/<SID>/<SID>/trace/alert_<SID>.log
```

動的パフォーマンスビューのV$DIAG_INFOをSELECT文で確認が可能。
```
SELECT NAME, VALUE FROM V$DIAG_INFO;
```

alert_<SID>.logには以下のエラーが出力されていた。
```
ORA-19809: リカバリ・ファイルの制限を超えています
ORA-19804: XXXバイトのディスク領域をXXXバイト制限から再利用できません
```

ORA-19809は高速リカバリ領域が不足したため発生したエラー。
高速リカバリ領域とはバックアップファイル、アーカイブログファイルなどのリカバリ関連のファイルの出力先となるディスク領域である。
高速リカバリ領域に出力されたファイルはOracle Databaseによって管理され、
初期化パラメータDB_RECOVERY_FILE_DEST_SIZEに設定されたサイズを超えないように制御される。

今回発生したエラーは、出力ファイルサイズがDB_RECOVERY_FILE_DEST_SIZEで指定したサイズを超えたため発生した。

## 復旧方法
DBサーバの復旧のため、高速リカバリ領域に出力されたファイルを削除する。
OSコマンドでファイル削除を行うと、Oracle Databaseが高速リカバリ領域の空きを認識しないため注意が必要。

DBサーバ上でRMANコマンドう実行しファイルを削除する。高速リカバリ領域の空きをOracle Databaseに認識させる。


**コマンドプロンプトからRMANを起動**
```
RMAN TARGET /
```

**マウントモードでの起動**
DBを起動できない状態のため、MOUNT状態にする。
```
RMAN> STARTUP MOUNT;
```

**アーカイブファイルと実際に存在しているアーカイブファイルの整合性チェック**
```
RMAN> CROSSCHECK ARCHIVELOG ALL;
```

**アーカイブログファイルの確認**
```
RMAN> LIST ARCHIVELOG ALL;
```

**アーカイブログファイルの削除**
```
RMAN> DELETE ARCHIVELOG ALL;
```

**削除後のアーカイブログの確認**
```
RMAN> LIST ARCHIVELOG ALL;
```

**DB起動**
```
RMAN> ALTER DATABASE OPEN;
```

DBが起動できるようになった。
再度処理をながすときは、DB_RECOVERY_FILE_DEST_SIZEを増やし対応する。
初期化パラメータファイルの値を変更後にDB再起動を行うか、ALTER SYSTEMコマンドで動的に変更できる。

## 参考
[Oracle Databaseの起動プロセス](https://www.ashisuto.co.jp/db_blog/article/oracledb-startup-trouble.html)
[ORA-19809](https://cosol.jp/knowledge/knowledge_post/ot0018_ora19809/)
usbipd-winでpersistedなデバイスをunbindする方法

## abstract
`upbipd list`で出てきたpersistedなデバイスの`GUID`を参照して以下のコマンドを実行

```powershell
usbipd unbind --guid #<GUID>
```

## background

- `WSL2`でUSBシリアルのデバイスを扱いたいとき，[usbipd-win](https://github.com/dorssel/usbipd-win)を使う
- `usbipd-win`は一度`usbipd bind`して`Shared`になったデバイスのGUIDを記録し保存しておく（この状態が`Persisted`）
    - これにより，次に同じデバイスをつなげたとき，もう一度`usbipd bind`をせずに済む．`usbipd attach`は毎回必要
    - `--auto-attach`というオプションつければ自動化できるっぽい
 ```powershell
`-a, --auto-attach                      Automatically re-attach when the device is detached or unplugged`
```
- ただしつなげる機器によって，なぜか毎回GUIDが生成されて別デバイスとして認識され，Persistedのリストがでかくなることがある
    - ![Untitled.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/265603/c0da70a5-754a-4a3f-bd9c-ccdcc130f7b9.png)
    - この例では`USB Serial Converter`とのみ表示されている機器がそれ．すでに何個か消した後
- リストが長くなってうざくなるので，消したいが，公式ページにはcommand や オプションに関するドキュメントが見当たらなかった[^1]
    - `bash`などにおける`man`コマンドの`powershell`版が`get-help`らしいので使ってみたが，エラーが起こるだけだった[^1]
- `usbipd bind`や`usbipd attach`などでは`BUSID`を指定するのだけれど，Persisted デバイスはコネクトされていないので，`BUSID`が表示されているわけもなく，`GUID`のみが表示される
- なので`usbipd unbind`のようなコマンドあり，かつ`GUID`を指定する`--guid`みたいなオプションがあればうれしい

## solution

[usbipd-winのgithubの関連するissue上](https://github.com/dorssel/usbipd-win/issues/852#issuecomment-1925253435)で，作者自身が投稿していたコメントにまさに必要なコマンドがまんま書かれていた．

```powershell
usbipd unbind --guid
```

## p.s.


[^1]: あとから気づいたが，`usbipd`とのみ実行すれば，オプションリストとコマンドリストが表示され，そこに`unbind`があり，`usbipd unbind`とのみ実行すればこれのオプションリストが表示され`usbipd unbind --guid`が存在することがわかるようであった