2023年4月27日 星期四

AdonisJs自動注入2

前言

上之介紹過adonisjs/fold的inject,讀過inject的源碼可以知道inject會把宣告的class直接注入進目前class的inject內的instance,而且是static,然後底層透過Route呼叫controller在把instance一一實現出來。那這樣問題來了,如果不是透過Route想要實現自動注入該如何處理。

例如Seeder中偶爾會寫一些腳本,但最好的方法是呼叫service執行相對應的function讓程式走已經經過測試的流程,才不會出現漏改或資料不完整等資料問題。那seeder並非透過route來呼叫,所以無法使用inject,在此我開發了一個套件供大家簡單使用

// install commands
yarn add @lu7766lu7766/adonis-utils
node ace invoke @lu7766lu7766/adonis-utils

// seeders
import BaseSeeder from '@ioc:Adonis/Lucid/Seeder'
import { InjectService } from '@ioc:Adonis/Utils'

export default class ProdDataChange0428 extends BaseSeeder {
@InjectService() // @InjectService(SurveyService)
service: SurveyService

public async run() {
console.log(this.service)
}
}

套件是開源的,源碼也很簡單,下面給大家展示一下。這也不限於只能使用在adonisjs上,甚至在其他專案也可以使用

export function InjectService(injectClass?: any) {
return function (target: Object, propKey?: string) {
if (propKey) {
const targetClass = injectClass ?? (Reflect.getMetadata("design:type", target, propKey) || [])
const params = Reflect.getMetadata("design:paramtypes", targetClass) || []
const service = new targetClass(...params)

Object.defineProperty(target, propKey, {
value: service,
writable: false,
})
}
}
}

後記

有些人喜歡用抽象或介面去管理程式碼,所以設計成參數可以設定要注入什麼,不輸入則自動注入類別,增加一點彈性。

5/23更新

我發現上面的源碼無法把注入的service,建構子裡的物件一並注入,簡單說他就是只有一層,如果要用到第二層的東西就掛了,所以我改用遞回方式去注入物件,下載到舊版的小夥伴記得去更版

2023年4月20日 星期四

git刪除(遠端)分支

因為VSCode沒有提供這個指令,而且也不常用到,所以我老是忘記,在此組個紀錄

git push [REMOTE_NAME] :[BRANCH_NAME]

想不到是用push吧,記得在要刪除的分支前面加個冒號!

順便講一下刪除本地分支的語法,因為VSCode有,所以其實也不用特別記,只是想講

git branch -d [BRANCH_NAME]


當MySQL遇上死鎖ER_LOCK_WAIT_TIMEOUT

當MySQL資料庫處理時遇到ER_LOCK_WAIT_TIMEOUT時,代表該表有交易還沒結束掉,要查詢到底是哪一筆交易沒結束掉可以使用以下SQL,DB_NAME請替換成自己的資料庫名稱

SELECT CONCAT('KILL ', ID, ';')
FROM INFORMATION_SCHEMA.PROCESSLIST
WHERE DB = [DB_NAME] AND TIME >= 10;

之後可以得到該執行序的id,然後直接下SQL,上面這個語法直接幫你把要下的SQL組合起來了,下完就海闊天空了~

KILL [ID];

AdonisJs踩雷第二發Computed

故事是這樣的,我Model有一個欄位用來儲存json字串,然後訂了一個computed欄位自動分析json,所以我很直覺地把分析完的結果拿來修改,再轉為json字串存回去,結果搞了半天內容卻一點變化也沒有。

殊不知computed是不能修改的,底層大概率是用Object.freeze之類的把物件凍結了吧。之後有空再來研究,今天先做個紀錄。

AdonisJs踩雷的一天, Migration completed, but unable to release database lock...

如果在Migration時遇到如標題所示的錯誤訊息,網路上找也只能找到這則相關的資訊,https://github.com/adonisjs/core/discussions/1897

只能說我看完當下完全看不懂他在說些什麼。

經過反覆的測試,才漸漸理解,原來發生的原因是query出錯,更正確的說法是程式報錯,至於錯在哪裡並不會告訴你,可能跟底層跑migration的方式有關,所以比較理想的解法是盡可能讓migration的sql簡單不要報錯,至於那些寫在defer裡面的query跟scripts,請抽離並改用seeder去觸發(這時就會看到錯在哪了,可以順便debug)是比較理想的做法。

另外在跑腳本可能會因為執行時間太長而中止,所以請減少sql的數量,盡可能一次取回所有資料,能把update delete insert塞進一個sql裡面就盡可能塞,減少使用關聯,才能確保腳本跑得完



2023年4月11日 星期二

SQL在眾多時間中要選出最大的時間

 可以使用GREATEST去篩選出最後一個時間

select GREATEST(
updated_at,
   created_at
) as last_updated_at`
from users

如果很不幸遇到時間是null的,需要再加一層函式

select GREATEST(
COALESCE(updated_at, 0)
COALESCE(created_at, 0)
) as last_updated_at`
from users

這樣就可以確保輸出有值了

如果是js要處理這樣的狀況,那就簡單多了,使用lodash的max把所有時間都當成參數即可