見出し画像

あると便利かもしれないスニペット集

あると便利かもしれないものたち

みなさんこんにちは、ALH開発事業部のREIYAです。

かゆいところに手が届くようなパーツをまとめてみました。
もちろん場面や人によると思いますがぜひご一読ください。
今回の記事では以下だけです。今後にご期待ください。


※一応言語ごとにまとめてますが、やっていることはバラバラなので許してね

Docker

Dockerfile

思うにイメージレイヤの最適化が拙かった時代のせいで私含めコマンドワンライナー芸人いまだに多いし、マルチステージビルドでバグらせることあるから全人類Dockerfileの書き方統一して欲しい

FROM python:3.11.4-slim-bullseye

WORKDIR /asset

COPY ./app /asset/app

RUN cd app \
    && python -m pip install -U pip \
    && python -m pip install -r requirements.txt \
    && chmod 777 some_file

CMD ["python", "app/server.py"]

pod監視

podを眺めておきたい時用

# とにかくみる
watch -n 1 -d kubectl get pod

# 全pod名
kubectl get pods -o jsonpath='{.items[*].metadata.name}'

番号指定で入る

環境によって動かないので注意

no=3
tmp=$(kubectl get pods -o jsonpath='{.items[$no].metadata.name}')
kubectl exec -it $tmp /bin/bash

docker単品

# ビルドタグ付け起動
cd ~/パス \
&& docker build -t コンテナ名:latest . \
&& docker images | grep -e 'コンテナ名' -e 'latest' | awk '{print $3}' | xargs -I{} docker run {}

# ポート結びつけ
cd ~/パス
sudo docker build -t コンテナ名:latest .
sudo docker run -p 8080:8080 コンテナ名:latest
# host : container

# いろいろ操作
sudo docker ps -a
sudo docker stop {running container id}
sudo docker rm {id1} {id2} ...
sudo docker images
sudo docker rmi {id1} {id2} ...

# pullからワンライナー
git pull \
&& sudo docker build -t コンテナ名:latest . \
&& sudo docker run -d -p 8080:8080 コンテナ名:latest

docker単品のバインドとかする系

docker build -t IMAGENAME:latest . \
  && docker run \
    --name NAME \
    -d \
    -p 8080:8080 \
    -v "$(pwd)/../フォルダ:/asset/どっか" \
    NAME:latest

# コンテナ停止 + 削除 (コンテナ名重複を防ぐ)
docker stop $(docker ps -aq -f name=NAME)
docker rm $(docker ps -aq -f name=NAME)

# 停止コンテナ全削除 + <none>なイメージ全削除
docker container prune
docker rmi $(docker images -f "dangling=true" -q)

Java

mutex

昨今は手動でやることあんまないかもですが、ふと排他したい時に便利。

public static void exclusive(Consumer<String> job, String procNm) {
  File file = new File("ロックファイルパス");
  try (FileChannel channel = FileChannel.open(file.toPath(), StandardOpenOption.CREATE, StandardOpenOption.WRITE);) {
    FileLock lockedObject = channel.tryLock();
    job.accept(procNm);
    lockedObject.release();
  } catch(OverlappingFileLockException e) {
  } catch(IOException e) {
  }
}

Function作る

型が多いとこんがらがりますよね。コピペしていきましょう

@FunctionalInterface
private interface MyFunc<T, S, U> {
  void exe(T e1, T e2, S e3, U e4);
}

やけくそstream

中間と終端とりあえず書きまくっておいて必要なとこだけにしたらいい。

IntStream.rangeClosed(1, 10).boxed().forEach(System.out::println);
Arrays.asList("a").stream()
.filter(v -> "constant".equals(v))
.filter(predicate)
.map(Entity::getValue)
.map(v -> {
  return v;
})
.peek(System.out::println)
.flatMap(l -> l)
.sorted()
.forEach(v -> {});
.collect(Collectors.joining(","));
.collect(Collectors.toList());
.collect(Collectors.toMap(e -> e.getId(), e ->  e,
(l,  r) ->  r // 重複時後勝ち
,));
,LinkedHashMap::new)); // 順序付き
.collect(Collectors.groupingBy(Entity::getId, Collectors.mapping(Entity::getName, Collectors.toList())));

mapループ

意外と書くことが多い気がする

for (Entry<String, String> e : mp.entrySet()) {
  e.getKey();
  e.getValue();
}

本当はこう書きたい。JSとかCならいけます

for (auto &&[key, val] : map) {
}

スレッドセーフカウンタ

スレッドごとに持つだけ。カウンタでなくてもいい

private ThreadLocal<Integer> threadSafeCnt = new ThreadLocal<Integer>() {
  @Override 
  protected Integer initialValue() {
    return 1;
  }
};
private void dfs() {
  int cnt = threadSafeCnt.get();
  System.out.println("いま" + cnt + "週目");
  if (cnt == 5) {
    threadSafeCnt.set(1);
    return;
  }
  threadSafeCnt.set(cnt++);
  dfs();
}
dfs();

スレッドセーフリスト

追加削除はこれで同期される

List<String> list = Collections.synchronizedList(new  ArrayList<String>());

Python

lambda

ラムダが書きにくい言語って結構多い印象

odd = lambda v: v & 1
print([v for v in filter(odd, range(10))])

回数だけループ

for _ in [0] * 3: # どうでもいいがこっちのが早いらしい
    print("ok")
for v in range(3): # 同じこと
    print("ok")

デコレータ

たまにこんがらがるので。

import functools
def decorator_template():
    def some(func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            # do something
            return func(*args, **kwargs)
        wrapper.__name__ = func.__name__
        return wrapper
    return some

lower_bound

upperはrightだね

import bisect
prime = [2, 3, 5, 7, 11, 13, 17, 19]
print(bisect.bisect_left(prime, 11)) # 4

# x以下の最大
def ika(arr, x):
    i = bisect.bisect_right(arr, x)
    if i:
        return a[i-1]

pandas

結構忘れるのでまとめておきましょう。
接続系はプールしてるかなどで変わるのでよしなに。

def select(query, data_json):
    """SELECT as DataFrame
    :param string SQL query
    :param json Binding Parameters JSON
    :return DataFrame
    """
    return _read(_select, query, data_json)

def _select(con, query, data_json):
    c = con.cursor()
    q = c.execute(query, data_json)
    cols = [column[0] for column in q.description]
    results = pandas.DataFrame.from_records(data=q.fetchall(), columns=cols)
    c.close()
    return results

def insert(table, df_json):
    """INSERT DataFrame
    :param string Table Name
    :param json DataFrame JSON such as [{'columname': 'value'}]
    """
    _exe(_insert, table, df_json)

def _insert(con, table, df_json):
    pandas.DataFrame(df_json).to_sql(table, con, if_exists='append', index=False)

def _get_db():
    """Open connection
    """
    con = sqlite3.connect(なにか)
    return con

def _read(func, *args):
    """read & close
    """
    con = _get_db()
    res = func(con, *args)
    con.close()
    return res

def _exe(func, *args):
    """execute & commit
    """
    con = _get_db()
    res = func(con, *args)
    con.commit()
    con.close()
    return res, con

def delete(sql, json):
    con = _get_db()
    con.execute(sql, json)
    con.commit()
    con.close()

使い方サンプル

query = 'SELECT id FROM table WHERE name like :name'
args = dict(name='%test%')
df = select(query, args)
df.iat[0, 0] # 0行目0列目
res = df.to_json(orient='records')
obj = json.loads(res)  # if empty, string "[]"

sqlite前提でもっと簡潔に

import sqlite3
import pandas as pd

def _get_db():
    return sqlite3.connect("DBファイルパス")

def select(query, data_json):
    con = _get_db()
    cur = con.cursor()
    q = cur.execute(query, data_json)
    res = pd.DataFrame.from_records(data=q.fetchall(), columns=[col[0] for col in q.description])
    cur.close()
    con.close()
    return res

def get(query, cols):
    con = _get_db()
    cur = con.cursor()
    q = cur.execute(query)
    res = pd.DataFrame.from_records(data=q.fetchall(), columns=cols)
    cur.close()
    con.close()
    return res

def exe(sql, json):
    con = _get_db()
    con.execute(sql, json)
    con.commit()
    con.close()

使い方

import json
from どこか import ふぁいる as sql

def sample():
    # select 1行1列
    query = "SELECT id FROM table WHERE val = :val"
    df = sql.select(query, {"val": 10})
    _ = df.iat[0, 0]

    # select 全部
    query = "SELECT id, name, val FROM table WHERE val = :val"
    df = sql.select(query, {"val": 10})
    res = df.to_json(orient='records')
    _ = json.loads("[]" if res is None else res)

    # カスタムquery
    query = """
    WITH some AS (
        SELECT some FROM table LEFT JOIN AAA ...
    )
    SELECT aaa, aaa, ... FROM table
    INNER JOIN some sub ON table.id = some.id
    """
    col = ["id", "name", "some", ..... ]
    res = sql.get(query, col).to_json(orient='records')

    # insert
    # update
    # delete
    query = "DELETE table WHERE id = :id"
    sql.exe(query, {"id": 5})

Base64+json

Base64変換でJSON連携する際のトラップで、PythonでBase64変換すると「'」などが入りJSONが壊れる。

import base64
import json
request_str = 'この文字列をBase64変換した状態で送りたい'
# str -> bytes -> base64 -> str
data_bytes = bytes(request_str, 'utf-8')
data_encode_bytes = base64.b64encode(data_bytes)
data_encode_str = data_encode_bytes.decode('utf-8')
request_dict = {
    'data': data_encode_str
}

Go

起動とか

goじゃなくてshellですが...
直起動してるならポートでkillしてpullからのあげ直しをデタッチみたいなことしますよね。

# run
go run .

# checkport
lsof -P -i:8080
kill {PID}

# sequence
lsof -P -i:8080 | awk 'NR==2 {print $2}' | xargs -t -I{} kill {} && git pull && go build && nohup ./appname &

レシーバ用意

// struct def
type ko struct {
	oya oya.Ko
}
type Ko interface {
	Create(c *gin.Context)
}

func NewKo() Ko {
	return &ko{sql.KoIni()}
}

// Imprementation
func (ko *ko) Create(c *gin.Context) {
	// some
}

WebSocket

GinとMelodyでwebsocketしたいとき。
というかWebSocketは大体全部同じ感じになるので言語関係なくこれみたらいいと思う

package some

import (
	"encoding/json"
	"log"
	"strconv"
	"strings"
	"sync"

	"github.com/gin-gonic/gin"
	"github.com/olahol/melody"
)
var m *melody.Melody

func WSIni() {
	m = melody.New()
	lock := new(sync.Mutex)

	// on connected
	m.HandleConnect(func(s *melody.Session) {
		log.Printf("#### websocket connection open. [session: %#v]\n", s)
		lock.Lock()

		// 部屋idみたいなのがURLにあるとする
		reqUris := strings.Split(s.Request.URL.String(), "/")
		roomId := reqUris[len(reqUris)-1]
		i, _ := strconv.Atoi(roomId)
		msgs := // 部屋iのメッセージを取得する
		jsonstring, err := json.Marshal(msgs)
		if err != nil {
			log.Fatal(err.Error())
		}
		s.Write(jsonstring)

		lock.Unlock()
	})

	// on disconnected
	m.HandleDisconnect(func(s *melody.Session) {
		message := "#### websocket disconnected."
		s.Write([]byte(message))
		log.Printf("#### websocket connection close. [session: %#v]\n", s)
	})

	// on message
	m.HandleMessage(func(s *melody.Session, msg []byte) {
		lock.Lock()

		// 部屋idみたいなのがURLにあるとする
		reqUris := strings.Split(s.Request.URL.String(), "/")
		roomId := reqUris[len(reqUris)-1]
		i, _ := strconv.Atoi(roomId)
		// insert reqeust
		var req なんらかのモデル
		if e := json.Unmarshal(msg, &req); e != nil {
			log.Fatal(e.Error())
		}
		userid, _ := strconv.Atoi(req.UserId)
		DBに登録(i, userid, req.Msg)

		// 今のメッセージを、同じ部屋の全員に送る
		sessions, err := m.Sessions()
		if err != nil {
			log.Fatal(err.Error())
		}
		for _, v := range sessions {
			uri := strings.Split(v.Request.URL.String(), "/")
			joindroomId := uri[len(uri)-1]
			// broadcast only same room (including me)
			if roomId == joindroomId {
				v.Write(msg)
			}
		}
		message := string(msg)
		log.Printf("[accept message]:%s", message)
		lock.Unlock()
	})
}

func MsgSync(c *gin.Context) {
	m.HandleRequest(c.Writer, c.Request)
}

おわり

だいぶ統一感ないですが許してください。
他言語も別記事で出します。

ALHについて知る



↓ ↓ ↓ 採用サイトはこちら ↓ ↓ ↓


↓ ↓ ↓ コーポレートサイトはこちら ↓ ↓ ↓


↓ ↓ ↓ もっとALHについて知りたい? ↓ ↓ ↓