LoginSignup
0
0

シェルスクリプトと SQLite3 で Nostr のリレーサーバ(っぽいの) (2) REQ と CLOSE に対する out.sh の処理

Posted at

REQ に対しての処理の外側

実際に求められたデータを流す部分はバックグラウンドで実行する。何故ならばある REQ リクエストが求められている間にも他のリクエストが来て、それを処理しなくてはならなくなることもあるからだ。これを in.sh として別に作るが、取り敢えずは out.sh を書き続ける。

bash in.sh "$second_element" "third_element" &
inner=$!

と "&" を付ければバックグラウンド(別プロセス)で同時進行できる。しかしそのプロセスのID(PID)を保持しておかないと CLOSE が来ても kill できない。なので $! でそれを取得して変数 inner に入れている。それを REQ の次の要素、セッションID と結びつけて保つことにする。これには連想配列を使う。なので while の上で

declare -A req_rec=()

と連想配列を宣言しておく。req_rec は REQ のレコードくらいの意味でつけた。この配列に

session_id=$(tr -d '"' <<< $second_element) # REQ のセッションID
req_rec[$session_id]=$inner # 連想配列にセッションIDをキーにPIDを収める

と、REQ に応じる in.sh のプロセスIDをセッションIDとセットで追加する。
in.sh の内容は後で記す。取り敢えず REQ に対する out.sh の処理は

elif [ "$first_element" = '"REQ"' ]; then

	bash in.sh "$second_element" "$third_element" &
	inner=$! # in.sh のプロセスID を inner に保持

	session_id=$(tr -d '"' <<< $second_element) # REQ のセッションID
	req_rec[$session_id]=$inner # 連想配列にセッションIDをキーにPIDを収める

とする。

CLOSE に対する処理

CLOSE が来たらセッションIDとセットになっているプロセスIDを kill し、req_rec 配列から削除すればよい。

elif [ "$first_element" = '"CLOSE"' ]; then

	session_id=$(tr -d '"' <<< $second_element) # CLOSE するのセッションID
	kill $( echo ${req_rec[$session_id]} ) # プロセスIDを kill し
	unset req_rec[$session_id] # req_rec から削除

out.sh の全文を以下に記すが、最初に trap 'kill $(jobs -p)' EXIT と書いておく。kill 漏れがあった場合でも out.sh を止めたとき全てのプロセスを kill するためだ。

out.sh
#!/bin/bash


trap 'kill $(jobs -p)' EXIT

declare -A req_rec=()

while read -r line; do
	first_element=$(echo $line | jq -c .[0])
	second_element=$(echo $line | jq -c .[1])
	third_element=$(echo $line | jq -c .[2:][])

	if [ "$first_element" = '"EVENT"' ]; then
	## 記録・保存
		id=$(echo $second_element | jq '.id' | tr -d '"')
		pubkey=$(echo $second_element | jq '.pubkey' | tr -d '"')
		kind=$(echo $second_element | jq '.kind')
		created_at=$(echo $second_element | jq '.created_at')

		tags=( $(echo $second_element | jq -c .tags[][1] | tr -d '"' |
								while read -r tag; do
								echo "$tag"
								done) ) # 配列化
		tag1=${tags[0]}
		tag2=${tags[1]}
		tag3=${tags[2]}
		tag4=${tags[3]}

		sqlite3 test.db "insert into forRelay (created_at, id, author, kind, tag1, tag2, tag3, tag4) values ('$created_at', '$id', '$pubkey', '$kind', '$tag1', '$tag2','$tag3','$tag4');" # シングルクォート大事
		echo $second_element > ./jsons/$created_at
		echo "[\"OK\",\"$id\",true,\"\"]"
	## 記録・保存 ここまで

	elif [ "$first_element" = '"REQ"' ]; then

		bash in.sh "$second_element" "$third_element" &
		inner=$! # in.sh のプロセスID を inner に保持

		session_id=$(tr -d '"' <<< $second_element) # REQ のセッションID
		req_rec[$session_id]=$inner # 連想配列にセッションIDをキーにPIDを収める


	elif [ "$first_element" = '"CLOSE"' ]; then

		session_id=$(tr -d '"' <<< $second_element) # CLOSE するのセッションID
		kill $( echo ${req_rec[$session_id]} ) # プロセスIDを kill し
		unset req_rec[$session_id] # req_rec から削除

	else echo "[NOTICE]" # これで誤魔化す
	fi
done

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0