跳至內容
Astera Technology

搬移名稱已用過,腳本變了為何仍要停?

認作已完成步驟前,要比所存腳本摘要是否一致。

下載完整個案資料及參考答案 ↓

先核來源與已訂規則

本例固定本地腳本把數量加 1 或 2。已用 V2 是加 1,且記 SHA-256。再以 V2 放加 2,是不同內容;只看名卻當已完成。更正要比真正腳本摘要。

已填假設輸入
紀錄輸入 JSON
原例輸入{"version":"V2","script":"UPDATE target SET quantity=quantity+2;"}
下載可編輯 CSV ↓

比較兩條實際路徑

已變 V2 暫停,數量 2 與原記錄照留。V2/內容全符才認重跑;新 V3 才執行所附加 2 並記自己身分。

錯誤與更正路徑的輸出
路徑輸出 JSON
錯誤路徑{"accepted":true,"error":null,"applied":false,"quantity":2,"versions":["V2"]}
更正路徑{"accepted":false,"error":"changed-script","applied":false,"quantity":2,"versions":["V2"]}
下載可編輯 CSV ↓
本地 Node.js 程序:22.23.3 或 24.14.1
import {DatabaseSync} from 'node:sqlite';
import {TextDecoder} from 'node:util';
import {inflateSync} from 'node:zlib';
import {posix} from 'node:path';
import {createHash} from 'node:crypto';
const rows=(db,sql)=>db.prepare(sql).all().map(r=>({...r}));
const failed=(action)=>{try{action();return null;}catch(e){return {code:e.errcode??e.code??e.name};}};

import assert from 'node:assert/strict';
const run=function run(i,corrected=true){
    if(!['V2','V3'].includes(i.version)||!['UPDATE target SET quantity=quantity+1;','UPDATE target SET quantity=quantity+2;'].includes(i.script))throw new Error('Outside the fixed local migration scripts');
    const db=new DatabaseSync(':memory:');try{db.exec('CREATE TABLE target(quantity INTEGER);INSERT INTO target VALUES(1);CREATE TABLE ledger(version TEXT PRIMARY KEY,hash TEXT);');
      const first='UPDATE target SET quantity=quantity+1;';const hash=s=>createHash('sha256').update(s).digest('hex');db.exec(first);db.prepare('INSERT INTO ledger VALUES(?,?)').run('V2',hash(first));
      const stored=db.prepare('SELECT hash FROM ledger WHERE version=?').get(i.version);let error=null,applied=false;
      if(stored){if(corrected&&stored.hash!==hash(i.script))error='changed-script';}
      else{db.exec('BEGIN;');db.exec(i.script);db.prepare('INSERT INTO ledger VALUES(?,?)').run(i.version,hash(i.script));db.exec('COMMIT;');applied=true;}
      return {accepted:error===null,error,applied,quantity:db.prepare('SELECT quantity FROM target').get().quantity,versions:rows(db,'SELECT version FROM ledger ORDER BY version').map(r=>r.version)};
    }finally{db.close();}
  };
const cases=[{"label":"misleading base","input":{"version":"V2","script":"UPDATE target SET quantity=quantity+2;"},"expected":{"accepted":true,"error":null,"applied":false,"quantity":2,"versions":["V2"]},"corrected":false},{"label":"corrected base","input":{"version":"V2","script":"UPDATE target SET quantity=quantity+2;"},"expected":{"accepted":false,"error":"changed-script","applied":false,"quantity":2,"versions":["V2"]},"corrected":true},{"label":"same version and exact same script","input":{"version":"V2","script":"UPDATE target SET quantity=quantity+1;"},"expected":{"accepted":true,"error":null,"applied":false,"quantity":2,"versions":["V2"]},"corrected":true},{"label":"new named migration step executes","input":{"version":"V3","script":"UPDATE target SET quantity=quantity+2;"},"expected":{"accepted":true,"error":null,"applied":true,"quantity":4,"versions":["V2","V3"]},"corrected":true}];
for(const test of cases){
  const actual=run(test.input,test.corrected);
  assert.deepEqual(actual,test.expected,test.label);
  console.log(test.label,actual);
}
下載可執行例子 ↓

下次載入前核邊界

同腳本不再執行;新 V3 把已有 2 加成 4,記 V2、V3。

可編輯邊界紀錄及預期輸出
情況輸入 JSON預期輸出 JSON
同名且腳本完全一致{"version":"V2","script":"UPDATE target SET quantity=quantity+1;"}{"accepted":true,"error":null,"applied":false,"quantity":2,"versions":["V2"]}
新命名搬移內容{"version":"V3","script":"UPDATE target SET quantity=quantity+2;"}{"accepted":true,"error":null,"applied":true,"quantity":4,"versions":["V2","V3"]}
下載可編輯 CSV ↓

版本名稱同 V2,是否已代表工作內容相同?

查看參考答案

不是,加 2 與已做加 1 不同。用 V2 的變更腳本要停,數量仍 2。

相關資源