นากกายต้นฉบับกำลังเลื่อนแฟ้มที่ปิดผนึกจากถาดเตรียมไปยังช่องเผยแพร่ในจังหวะเดียว

Java Files.move กับ ATOMIC_MOVE: เผยแพร่ไฟล์เมื่อเขียนเสร็จทั้งก้อน

พี่โชว์Engineering

ถ้าเขียน config หรือ report ลงชื่อจริงทีละ byte ผู้อ่านอีก process อาจเห็นไฟล์ครึ่งก้อนครับ รูปแบบที่ปลอดภัยกว่าคือเขียนไฟล์ชั่วคราวให้เสร็จ ปิด handle แล้วใช้ Files.move พร้อม ATOMIC_MOVE เพื่อให้การเปลี่ยนชื่อปรากฏเป็นจังหวะเดียวเมื่อ filesystem รองรับ

เหมือนเตรียมแฟ้มหลังเคาน์เตอร์จนเรียบร้อย แล้วสอดเข้า slot เผยแพร่ครั้งเดียว คนอ่านจะเห็นแฟ้มเก่าหรือแฟ้มใหม่ ไม่ควรเห็นหน้ากระดาษที่ยังเย็บไม่ครบ

import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;

public class Main {
    public static void main(String[] args) throws Exception {
        Path dir = Files.createTempDirectory("atomic-publish-");
        Path draft = dir.resolve("report.tmp");
        Path published = dir.resolve("report.txt");
        try {
            Files.writeString(draft, "complete", StandardCharsets.UTF_8);
            Files.move(draft, published, StandardCopyOption.ATOMIC_MOVE);

            assert Files.notExists(draft);
            assert Files.readString(published, StandardCharsets.UTF_8).equals("complete");
            System.out.println("atomic move test passed");
        } finally {
            Files.deleteIfExists(draft);
            Files.deleteIfExists(published);
            Files.deleteIfExists(dir);
        }
    }
}

Atomic มีขอบเขต

JDK ระบุว่า provider อาจยก AtomicMoveNotSupportedException เช่นย้ายข้าม filesystem ดังนั้นไฟล์ชั่วคราวควรอยู่ directory เดียวกับปลายทาง หาก fallback เป็น move ธรรมดา ต้องยอมรับและบันทึกว่า atomicity หายไป หรือเลือก fail-closed เมื่อไฟล์นี้เป็น boundary สำคัญ

เมื่อใช้ ATOMIC_MOVE behavior ตอนปลายทางมีอยู่เป็น implementation-specific และ option อื่นถูกละเลยตาม contract อย่าสมมติว่า REPLACE_EXISTING จะกำหนดผลร่วมกันได้ทุก provider หากต้องไม่ overwrite ให้ทำชื่อปลายทาง unique หรือใช้ primitive/lock ที่สัญญาตรงกับ storage นั้น และอย่าลืม durability: atomic visibility ไม่ได้แปลว่าข้อมูลถูก flush ลงสื่อถาวรแล้วทุกชั้น

Recap

  • เขียนและปิดไฟล์ชั่วคราวก่อน publish
  • วาง temp บน filesystem เดียวกับปลายทาง
  • จัดการ AtomicMoveNotSupportedException ตามระดับความเสี่ยง
  • แยก atomic visibility ออกจาก overwrite policy และ durability