Skip to content
isdnetworks
Go back

이력에는 생성이라고 찍혀 있었다

(수정됨)

이력 테이블에 이렇게 찍혀 있었다.

3월 14일 23:03   제출 생성 · 파일 report_43937812472.pdf

Table of contents

Open Table of contents

증상 — 이력과 자료가 안 맞았다

그런데 mdl_assign_submission 에는 1건뿐이었다.

[이력]   제출 생성 (3월 14일)
[제출]   1건, timecreated 3월 2일

생성됐다는데 timecreated 가 3월 2일인 것 하나뿐이었다.

문구가 자료와 어긋나면 둘 중 하나는 사실이 아니다. 이력은 사람이 아니라 코드가 남기는 것이라 처음에는 그쪽을 믿었다.

검증 — 시각 두 개를 봤다

그 1건의 두 시각을 함께 봤다.

SELECT FROM_UNIXTIME(timecreated), FROM_UNIXTIME(timemodified), id
  FROM mdl_assign_submission WHERE id = ?;
timecreated    3월 2일 ...
timemodified   3월 14일 23:02
파일           report_43937812472.pdf

timemodified 가 3월 14일이고 파일이 이력에 찍힌 것과 같았다.

timecreated 와 timemodified 가 며칠 차이가 났고 이력 시각은 뒤쪽과 붙어 있었다. 그 시점에 일어난 것은 생성이 아니라 갱신이었다.

원인 — 하위 층 기준의 문구

이렇게 놓으니 앞뒤가 맞아떨어졌다.

새 제출을 만든 게 아니라
기존 제출의 파일과 제출 시각을 덮어씀
timecreated 는 그대로
timemodified 만 갱신

이력 문구는 생성인데 실제로는 갱신이었다.

이력 문구를 남기는 자리를 grep 으로 찾았다.

$this->add_history($file, '제출 생성 · 파일 ' . $filename);

add_history 가 붙어 있는 대상이 하위 항목이었다.

assignsubmission_file   새로 생김   ← "생성"
assign_submission       기존 것 갱신

assignsubmission_file 기준으로는 그 문구가 생성인 것이 맞았다.

같은 사건이라도 어느 층에서 보느냐에 따라 생성이기도 하고 갱신이기도 하다. 문구가 틀린 것이 아니라 그것이 무엇에 대한 것인지를 내가 잘못 읽은 것이었다.

교훈 — 같은 측정의 반복

이 건을 조사하면서 오진을 두 번 했다.

[1차]  제출 1건 → 재제출 안 함
[2차]  다시 세어 봄 → 여전히 1건 → 재제출 안 함

같은 방법으로 두 번 세면 두 번 다 같은 답이 나온다.

세 번째 확인에서는 아예 다른 것을 봤다.

[1·2차]  건수
[3차]    timecreated 대 timemodified, 그리고 이력

건수를 다시 세는 것 대신 두 시각을 대조하는 쪽을 골랐다. 이유는 같은 측정을 반복하는 것은 확인이 아니라서다. 세는 것에서 대조하는 것으로 바꾸니 그때 판정이 갈렸다.

COUNT 라는 측정 자체가 틀렸는데 그것을 반복해서 확인한 것이었다. 같은 측정을 반복하는 것은 확인이 아니다.

판단 기준 — 두 시각의 대조

이 유형의 판별법을 적어 뒀다.

SELECT timecreated, timemodified FROM mdl_assign_submission WHERE userid = ? AND assignment = ?;
같으면   손댄 적 없음
다르면   뭔가 갱신됨   ← 이력으로 확인

제출이 1건뿐인 것만 보고 재제출을 안 했다고 단정하지 않는다.

이력과 두 시각을 반드시 대조한다. 건수만 세고 있으면 덮어쓰기가 있었는지 없었는지가 아예 안 갈린다.

주의 — 오염된 경과일

이 덮어쓰기가 timecreated 를 쓰는 다른 계산에 영향을 줬다.

$elapsed = (time() - $submission->timecreated) / 86400;
if ($elapsed > 7) { /* 기한 초과 */ }

timecreated 기준으로 경과일을 재는 자리가 있었다.

timecreated   3월 2일
재제출        3월 14일
경과일 계산   → 12일

재제출 직후인데 elapsed 가 12일이라 이미 기한 초과로 잡힌다.

덮어쓰기 설계 때문에 timecreated 가 가장 최근 제출 시점이 아니게 됐고 그것을 기준으로 재는 계산이 전부 틀어졌다.

grep -rn "submission->timecreated" local/dlp/

timecreated 를 쓰는 자리를 전부 찾아 그 뜻이 유효한지 확인했다.

덮어쓰기가 있는 표에서 그 컬럼은 최초 생성이지 최근 동작이 아니다. 한 곳의 설계 선택이 무관해 보이는 곳을 깬다.

정리


Share this post on:

Previous Post
외부 시스템의 성공 응답을 그대로 믿지 않게 된 이유
Next Post
두 벌 중 하나 고르기