DDD, Saga & Pengadaan-acara: Dapatkah Tindakan Kompensasi hanya menjadi penghapusan di toko acara?

15

Saya menyadari pertanyaan di atas mungkin menimbulkan beberapa 'apa ??', tetapi izinkan saya mencoba menjelaskan:

Saya mencoba membungkus kepala saya pada beberapa konsep terkait, pada dasarnya pola-Saga ( http://www.rgoarchitects.com/Files/SOAPatterns/Saga.pdf ) dikombinasikan dengan Event-sourcing (A DDD-concept : http://en.wikipedia.org/wiki/Domain-driven_design )

Sebuah pos bagus yang merangkumnya bersama: https://blog.jonathanoliver.com/cqrs-sagas-with-event-sourcing-part-ii-ofofiiii/

Saya mendapatkan pertanyaan dalam satu menit, tetapi saya pikir saya harus mencoba untuk meringkas apa yang saya pahami terlebih dahulu (yang mungkin salah, jadi tolong perbaiki jika itu masalahnya) karena ini mungkin berdampak pada mengapa saya mengajukan pertanyaan untuk memulai dengan:

  1. Pola Saga adalah sejenis broker yang memberikan tindakan (pengguna akhir, otomatis, dll. Pada dasarnya apa pun yang akan mengubah data) membagi tindakan itu dalam aktivitas bisnis dan mengirimkan masing-masing aktivitas ini sebagai pesan ke Bus Pesan yang pada gilirannya mengirimkannya ke akar agregat masing-masing untuk dijaga.
  2. Akar agregat ini dapat beroperasi sepenuhnya secara mandiri (pemisahan keprihatinan yang bagus, skalabilitas yang luar biasa, dll.)
  3. Sebuah instance Saga sendiri tidak mengandung logika bisnis apa pun, yang terkandung dalam akar agregat yang dikirimnya aktivitas. Satu-satunya 'logika' yang terkandung dalam Saga adalah 'proses'-logika, (sering diimplementasikan sebagai Statemachine), yang menentukan berdasarkan tindakan yang diterima (serta acara tindak lanjut) apa yang harus dilakukan (yaitu: kegiatan apa yang harus dikirim)
  4. Saga-pola menerapkan semacam pola transaksi terdistribusi. Yaitu: ketika salah satu akar agregat (yang lagi-lagi bekerja secara mandiri, tanpa mengetahui keberadaan satu sama lain) gagal, seluruh tindakan mungkin harus dibatalkan.
  5. Ini diimplementasikan dengan memiliki semua akar agregat, setelah menyelesaikan laporan aktivitas mereka kembali ke Saga. (Dalam hal sukses dan kesalahan)
  6. Jika semua akar agregat mengembalikan sukses, statemachine internal jika Saga menentukan apa yang harus dilakukan selanjutnya (atau memutuskan itu selesai)
  7. Jika terjadi kegagalan, Saga mengeluarkan semua akar agregat yang mengambil bagian dalam tindakan terakhir yang disebut Tindakan Kompensasi, yaitu: tindakan untuk membatalkan tindakan terakhir yang dilakukan masing-masing akar agregat.
  8. Ini mungkin hanya melakukan 'Minus 1 suara' jika tindakan itu "ditambah 1 suara" tetapi bisa lebih rumit seperti mengembalikan posting blog ke versi sebelumnya.
  9. Pengadaan-acara (lihat posting blog yang menggabungkan keduanya) bertujuan untuk mengeksternalisasi menyimpan hasil dari setiap kegiatan yang dilakukan oleh masing-masing akar agregat ke Toko Acara yang terpusat (perubahannya disebut 'peristiwa' dalam konteks ini)
  10. Toko Acara ini adalah 'versi tunggal kebenaran' dan dapat digunakan untuk memutar ulang keadaan semua entitas hanya dengan mengulangi peristiwa yang disimpan (pada dasarnya seperti log peristiwa)
  11. Menggabungkan keduanya (yaitu: membiarkan akar agregat menggunakan Peristiwa-sumber untuk melakukan outsourcing menyimpan perubahan mereka sebelum melaporkan kembali ke Saga) memungkinkan banyak kemungkinan bagus, salah satunya menyangkut pertanyaan saya ...

Saya merasa saya harus melepaskan ini dari pundak saya, karena banyak yang harus dipahami dalam sekali jalan. Dengan konteks / pola pikir ini (sekali lagi, harap perbaiki jika salah)

pertanyaannya: Ketika root agregat menerima Tindakan Kompensasi dan jika akar agregat itu melakukan outsourcing perubahan keadaan menggunakan sumber-Peristiwa, bukankah Tindakan Kompensasi dalam semua situasi hanya akan menghapus peristiwa terakhir di Toko Acara untuk itu diberikan Agregat Root? (Dengan asumsi implementasi yang bertahan memungkinkan penghapusan)

Itu masuk akal bagi saya banyak (dan akan menjadi manfaat besar lain dari kombinasi ini) tetapi seperti yang saya katakan saya mungkin membuat asumsi ini berdasarkan pada pemahaman konsep-konsep ini yang salah / tidak lengkap.

Saya harap ini tidak terlalu panjang lebar.

Terima kasih.

Geert-Jan
sumber

Jawaban:

9

Anda tidak harus menghapus acara dari toko acara Anda. Ini mewakili sesuatu yang terjadi. Jika sesuatu terjadi sekarang, maka Anda harus mengetahuinya juga, oleh karena itu tambahkan acara yang akan memaksa agregat Anda untuk kembali ke keadaan sebelumnya. Sayang sekali menghapus informasi dari basis data Anda.

pikirkan contoh gerobak dari greg young dan item yang dihapus. Mungkin besok informasi tindakan kompensasi mungkin bernilai apa pun ..

Adapun saga, semuanya benar, sejauh yang saya tahu sendiri. Anda harus menganggap saga sebagai mesin negara. Itu hanya itu.

Ini adalah Perintah yang dikeluarkan saga untuk memberi tahu kelompok agregasi untuk melakukan sesuatu. Dari aksi ini akan ada acara. Acara ini mungkin merupakan tindakan korektif yang Anda butuhkan, atau mungkin perlu dinormalisasi dalam tampilan sehingga beberapa pengguna akan melihatnya untuk memutuskan apa yang harus dilakukan.

Itu tergantung pada aturan bisnis Anda. Entah, ada perbaikan yang mudah: root agregat tahu bahwa dalam kasus seperti itu, Anda melakukan itu, atau pilihannya terlalu rumit untuk dilakukan secara terprogram (biaya pengembangan terlalu tinggi) dan oleh karena itu, Anda dapat mengusulkan ini kepada beberapa pengguna, yang mungkin memilih antara tindakan yang berbeda. Semuanya tergantung pada konteks tindakan kompensasi. Ini adalah aturan bisnis murni. Apa yang harus kita lakukan dalam kasus ini atau itu. Ini adalah sesuatu untuk ditanyakan kepada pakar domain Anda, dan kemudian pilih bersamanya, apakah lebih baik untuk mengembangkan solusi otomatis atau jika solusinya adalah meminta pengguna Ronald R., karena dialah yang biasanya menjawab pertanyaan ini.

Arthis
sumber
Bagaimana kelompok agregasi mengetahui negara mana yang akan dikembalikan? Apakah itu diizinkan untuk melakukan query terhadap toko acara atau sesuatu?
Geert-Jan
Seharusnya tidak dikembalikan tetapi tambahkan acara lain. Ini adalah Perintah yang dikeluarkan saga untuk memberi tahu kelompok agregasi untuk melakukan sesuatu. Dari aksi ini akan ada acara.
Arthis
Ya saya mengerti. "Kembalikan" mungkin salah pilih. Pertimbangkan yang berikut ini: Saya mungkin ingin menggunakan Event Sourcing dengan Sagas untuk pemodelan, antara lain, arus penerbitan dokumen / persetujuan. Bagaimana jika seorang editor telah mengirim tindakan ChangeBlogBody yang pada akhirnya bertahan sebagai acara BlogBodyChanged ke Event Store. Setelah itu, untuk beberapa alasan, Tindakan Kompensasi dikeluarkan. Bagaimana Agregat tahu kompensasi apa yang memecat acara yang menghasilkan isi Badan Blog seperti sebelum aksi ChangeBlogBody dikeluarkan?
Geert-Jan
Itu tergantung pada aturan bisnis Anda. Entah, ada perbaikan yang mudah: root agregat tahu bahwa dalam kasus seperti itu, Anda melakukan itu, atau pilihannya terlalu rumit untuk dilakukan secara terprogram (biaya pengembangan terlalu tinggi) dan oleh karena itu, Anda dapat mengusulkan ini kepada beberapa pengguna, yang mungkin memilih antara tindakan yang berbeda.
Arthis
Semuanya tergantung pada konteks tindakan kompensasi. Ini adalah aturan bisnis murni. Apa yang harus kita lakukan dalam kasus ini atau itu. Ini adalah sesuatu untuk ditanyakan kepada pakar domain Anda, dan kemudian pilih bersamanya, apakah lebih baik mengembangkan solusi otomatis atau jika solusinya adalah meminta pengguna Ronald R., karena dialah yang biasanya menjawab pertanyaan ini.
Arthis
6

Untuk kelengkapan, saya berpikir untuk memasukkan cuplikan yang relevan dari Martin Fowler tentang cara untuk mengembalikan keadaan:

Selain acara yang bermain sendiri, sering juga berguna bagi mereka untuk dapat membalikkan diri.

Pembalikan adalah yang paling mudah ketika acara dilemparkan dalam bentuk perbedaan. Contohnya adalah "tambahkan $ 10 ke akun Martin" sebagai kebalikan dari "atur akun Martin menjadi $ 110". Dalam kasus sebelumnya saya dapat membalikkan dengan hanya mengurangi $ 10, tetapi dalam kasus terakhir saya tidak memiliki informasi yang cukup untuk menciptakan kembali nilai masa lalu akun.

Jika acara masukan tidak mengikuti pendekatan perbedaan, maka acara tersebut harus memastikan ia menyimpan semua yang diperlukan untuk pembalikan selama pemrosesan. Anda dapat melakukan ini dengan menyimpan nilai sebelumnya pada nilai apa pun yang diubah, atau dengan menghitung dan menyimpan perbedaan pada acara tersebut.

Dari: http://martinfowler.com/eaaDev/EventSourcing.html

Geert-Jan
sumber
1

Secara konseptual:

  • Peristiwa adalah sesuatu yang terjadi. Masa lalu tidak bisa diubah.
  • Perintah adalah sesuatu yang harus dilakukan. Perintah mungkin tidak terjadi (dapat ditolak).

Kami hanya dapat mengubah status kami di masa mendatang dengan menjalankan perintah lain (Tindakan Kompensasi) yang akan menghasilkan Peristiwa yang mengubah keadaan aplikasi.

Untuk "tidak mengacaukan" pertanyaan, pikirkan frasa "hapus acara terakhir" ini:

  • Bagaimana jika acara terakhir bukan yang harus dihapus? Bagaimana jika peristiwa lain terjadi setelah yang akan dihapus? Peristiwa ini harus diubah juga (karena keadaan dasar mereka akan berubah dengan menghapus acara sebelumnya).
  • Bagaimana jika acara dikirim ke sistem eksternal? Anda mungkin tidak memiliki akses untuk memperbaiki keadaannya selain mengirim acara lain.

Singkatnya, Anda tidak memiliki opsi untuk menghapus acara dalam pola CQRS.

Anda dapat mengecilkan Event Store Anda dengan membuat snapshot state (yang didasarkan pada semua peristiwa yang mengarah ke state itu), tetapi aspek fisik ini tidak ada hubungannya dengan konsep acara.

uvsmtid
sumber
0

Geert-Jan, saya juga berpikir tindakan kompensasi dapat dengan mudah menghapus acara yang sesuai. Masuk akal dan menunjukkan manfaat lain dari pola desain Event Sourcing: implementasi yang lebih mudah dari pola desain Transaksi Kompensasi.

Beberapa mengatakan menghapus acara itu melanggar "prinsip" dari sumber acara atau CQRS. Saya pikir itu adalah generalisasi yang membatasi. Saya pikir tidak apa-apa untuk menghapus suatu acara jika itu dibuat dalam lingkup transaksi global yang sedang dibatalkan. Pertimbangkan kodesemu:

try {
    newEvents = processMycommand(myCommand)
    for (Event newEvent : newEvents)
        EventStore.insertEvent(newEvent);
} catch (Exception e) {
    EventStore.rollback();
}

Misalkan toko acara Anda adalah basis data transaksional. Di pseudocode, Anda bisa membayangkan situasi di mana Anda memasukkan acara pertama, tetapi ketika mencoba untuk memasukkan acara kedua sebuah Pengecualian dilemparkan. Perintah rollback secara alami akan mengembalikan penyisipan acara pertama. Apakah itu masuk akal?

Jika masuk akal untuk transaksi basis data ACID (transaksi dengan komit / kembalikan), mengapa tidak masuk akal untuk transaksi kompensasi?

Saat melakukan transaksi Saga global, perubahan data dapat dibatalkan (dengan kompensasi). Tidak perlu menyimpan acara yang dibuat selama transaksi karena transaksi tidak selesai.

Sekarang, jika kompensasi mencoba untuk menghapus suatu peristiwa dan peristiwa itu bukan peristiwa terbaru pada suatu objek, maka penghapusan tidak boleh terjadi. Tetapi secara umum, itu tidak mungkin terjadi, terutama dalam solusi intensif baca.

Paulo Merson
sumber
0

Mari kita bermain dengan pemikiran bahwa penyimpanan acara hanyalah data yang ingin Anda simpan. Misalnya kita dapat memiliki hard drive, kita bisa mulai dari awal dan menulis data di dalamnya. Setiap kali kami mendapat acara, kami menambahkan data kami sebelumnya, jadi kami terus menulis di disk tempat kami berhenti terakhir kali. Ketika kami ingin menghapus acara yang kami kembali, hapus bagian itu dari disk dan tinggalkan celah. Kembali dengan sendirinya memperlambat penyimpanan acara kami, tetapi kita bisa hidup dengan itu. Jika kita menggunakan sistem file, itu akan mencoba mengisi kekosongan dengan peristiwa yang terakhir, jadi kita akhirnya memiliki penyimpanan yang terfragmentasi lambat atau kita dapat melakukan defragmentasi. Tak satu pun dari mereka adalah sesuatu yang kita sukai. Jika kita berbicara tentang basis data, Anda mendapatkan ini jika Anda menggunakan basis data relasional alih-alih basis data tambahkan saja untuk menyimpan acara Anda:

masukkan deskripsi gambar di sini ref: https://cambridge-intelligence.com/bringing-time-series-data-to-life-with-keylines/

Ofc. oleh situs normal ini tidak masalah, tetapi solusi ini dirancang untuk situs web besar seperti facebook, google, dll ... Jadi pertanyaannya benar-benar tidak masuk akal, karena bagaimana Anda akan menghapus suatu peristiwa dalam menambahkan hanya basis data dan bagaimana Anda menyebut kompensasi sesuatu seperti membangun mesin waktu dan mundur dalam waktu untuk mengubah atau mencegah suatu peristiwa ???

Afaik. satu-satunya cara untuk mengatasi ini adalah membuat penyimpanan acara baru di mana Anda mengecualikan acara yang tidak Anda inginkan dan setelah itu menghapus penyimpanan acara lama. Tapi ini solusi ekstrem untuk menghapus satu peristiwa. Jika kita berbicara tentang GDPR, maka satu-satunya solusi yang relatif baik yang saya ketahui adalah menyimpan data pribadi yang dienkripsi di penyimpanan acara dan menghapus kunci enkripsi dari database yang berbeda.

inf3rno
sumber