Transaksi dalam REST?

147

Saya ingin tahu bagaimana Anda akan menerapkan use-case berikut di REST. Apakah mungkin untuk melakukannya tanpa mengorbankan model konseptual?

Baca atau perbarui beberapa sumber daya dalam lingkup satu transaksi. Misalnya, transfer $ 100 dari rekening bank Bob ke akun John.

Sejauh yang saya tahu, satu-satunya cara untuk mengimplementasikan ini adalah dengan menipu. Anda bisa POST ke sumber daya yang terkait dengan John atau Bob dan melakukan seluruh operasi menggunakan satu transaksi. Sejauh yang saya ketahui, ini memecah arsitektur REST karena Anda pada dasarnya melakukan tunneling panggilan RPC melalui POST daripada benar-benar beroperasi pada sumber daya individual.

Gili
sumber

Jawaban:

91

Pertimbangkan skenario keranjang belanja yang tenang. Keranjang belanja secara konseptual adalah pembungkus transaksi Anda. Dengan cara yang sama Anda dapat menambahkan beberapa item ke keranjang belanja dan kemudian mengirimkan keranjang itu untuk memproses pesanan, Anda dapat menambahkan entri akun Bob ke bungkus transaksi dan kemudian entri akun Bill ke bungkus. Ketika semua bagian sudah ada maka Anda dapat POST / PUT pembungkus transaksi dengan semua bagian komponen.

Darrel Miller
sumber
18
Mengapa TransferMoneyTransaction tidak menjadi sumber daya perbankan yang layak?
Darrel Miller
8
Jika Anda memastikan bahwa titik akhir Anda merujuk ke kata benda, maka biasanya intuitif apa yang akan dilakukan verba standar GET, PUT, POST, DELETE terhadap kata benda itu. RPC memungkinkan endpoint menjadi kata kerja sendiri dan karenanya dapat bertentangan dengan kata kerja HTTP dan maksudnya menjadi membingungkan.
Darrel Miller
10
mis. Apa yang terjadi jika Anda melakukan HTTP DELETE pada titik akhir UpdateXYZ? Apakah itu menghapus XYZ? Apakah itu menghapus Pembaruan atau hanya Pembaruan dan mengabaikan penghapusan kata kerja HTTP. Dengan menjaga kata kerja keluar dari titik akhir Anda menghilangkan kebingungan.
Darrel Miller
5
Dan bagaimana dengan transaksi di berbagai layanan? dan bagaimana ketika Anda ingin melakukan serangkaian perubahan 'tidak terkait' bahwa layanan tidak memunculkan wadah transaksi implisit .. ditambah, mengapa memiliki jenis transaksi tertentu ketika kami dipindahkan ke transaksi tujuan umum yang sama sekali tidak terkait dengan data aktual Anda perubahan. Transaksi mungkin tidak cocok dengan tenang, tetapi sepertinya transaksi harus berlapis-lapis, tidak terkait dengan panggilan lainnya selain dari fakta bahwa header permintaan akan berisi referensi transaksi.
meandmycode
4
@meandmycode Transaksi basis data harus berlapis di belakang antarmuka REST. Bergantian Anda dapat mengekspos transaksi bisnis (bukan transaksi basis data) sebagai sumber daya dalam dirinya sendiri dan kemudian Anda perlu mengambil tindakan kompensasi jika terjadi kegagalan.
Darrel Miller
60

Ada beberapa kasus penting yang tidak dijawab oleh pertanyaan ini, yang menurut saya terlalu buruk, karena memiliki peringkat tinggi di Google untuk istilah pencarian :-)

Secara khusus, propertly yang bagus adalah: Jika Anda POST dua kali (karena beberapa cache tersendat di perantara), Anda tidak boleh mentransfer jumlahnya dua kali.

Untuk mencapai ini, Anda membuat transaksi sebagai objek. Ini bisa berisi semua data yang Anda sudah tahu, dan menempatkan transaksi dalam status tertunda.

POST /transfer/txn
{"source":"john's account", "destination":"bob's account", "amount":10}

{"id":"/transfer/txn/12345", "state":"pending", "source":...}

Setelah Anda melakukan transaksi ini, Anda dapat melakukannya, seperti:

PUT /transfer/txn/12345
{"id":"/transfer/txn/12345", "state":"committed", ...}

{"id":"/transfer/txn/12345", "state":"committed", ...}

Perhatikan bahwa banyak penempatan tidak penting pada saat ini; bahkan GET pada txn akan mengembalikan kondisi saat ini. Secara khusus, PUT kedua akan mendeteksi bahwa yang pertama sudah dalam keadaan yang sesuai, dan hanya mengembalikannya - atau, jika Anda mencoba memasukkannya ke dalam keadaan "rollback" setelah itu sudah dalam keadaan "berkomitmen", Anda akan mendapatkan kesalahan, dan transaksi yang dilakukan sebenarnya kembali.

Selama Anda berbicara dengan satu database, atau database dengan monitor transaksi terintegrasi, mekanisme ini sebenarnya akan berfungsi dengan baik. Anda juga dapat memperkenalkan batas waktu untuk transaksi, yang bahkan dapat Anda ungkapkan menggunakan header Kedaluwarsa jika Anda menginginkannya.

Jon Watte
sumber
Diskusi yang menarik! Saya ingin menambahkan bahwa posting awal harus dilakukan dalam satu langkah. Tidak dapat ditambahkan lagi nanti (maka kita berada di wilayah keranjang belanja dan keranjang belanja memiliki banyak pemeriksaan dan saldo untuk mencegahnya menyebabkan kerugian bagi pengguna akhir, bahkan undang-undang, transfer bank tidak) ...
Erk
33

Dalam istilah REST, sumber daya adalah kata benda yang dapat ditindaklanjuti dengan kata kerja CRUD (create / read / update / delete). Karena tidak ada kata kerja "transfer uang", kita perlu mendefinisikan sumber daya "transaksi" yang dapat ditindaklanjuti dengan CRUD. Berikut ini contoh dalam HTTP + POX. Langkah pertama adalah MENCIPTAKAN (metode POST HTTP) transaksi kosong baru :

POST /transaction

Ini mengembalikan ID transaksi, misalnya "1234" dan sesuai URL "/ transaksi / 1234". Perhatikan bahwa menembakkan POST ini beberapa kali tidak akan membuat transaksi yang sama dengan beberapa ID dan juga menghindari pengenalan status "menunggu keputusan". Selain itu, POST tidak selalu idempoten (persyaratan REST), jadi umumnya praktik yang baik untuk meminimalkan data dalam POST.

Anda bisa membiarkan pembuatan ID transaksi hingga ke klien. Dalam hal ini, Anda akan POST / transaksi / 1234 untuk membuat transaksi "1234" dan server akan mengembalikan kesalahan jika sudah ada. Dalam respons kesalahan, server dapat mengembalikan ID yang saat ini tidak digunakan dengan URL yang sesuai. Ini bukan ide yang baik untuk meminta server untuk ID baru dengan metode GET, karena GET tidak boleh mengubah status server, dan membuat / menyimpan ID baru akan mengubah status server.

Selanjutnya, kami MEMPERBARUI (metode PUT HTTP) transaksi dengan semua data, secara implisit melakukan itu:

PUT /transaction/1234
<transaction>
  <from>/account/john</from>
  <to>/account/bob</to>
  <amount>100</amount>
</transaction>

Jika transaksi dengan ID "1234" telah PUT sebelumnya, server memberikan respons kesalahan, jika tidak, respons OK dan URL untuk melihat transaksi yang diselesaikan.

NB: di / akun / john, "john" harus benar-benar menjadi nomor akun unik John.

Tuckster
sumber
4
Menyamakan REST dengan CRUD adalah kesalahan serius. POST tidak harus berarti BUAT.
12
Kesalahan serius? Saya tahu ada perbedaan antara PUT dan POST, tetapi ada pemetaan yang longgar untuk CRUD. "Serius"?
Ted Johnson
3
Ya, serius. CRUD adalah cara penataan penyimpanan data; REST adalah cara penataan aliran data aplikasi. Anda dapat melakukan CRUD pada REST, tetapi Anda tidak dapat melakukan REST pada CRUD. Mereka tidak setara.
Jon Watte
20

Pertanyaan yang bagus, REST sebagian besar dijelaskan dengan contoh-contoh seperti basis data, di mana sesuatu disimpan, diperbarui, diambil, dihapus. Ada beberapa contoh seperti ini, di mana server seharusnya memproses data dengan cara tertentu. Saya tidak berpikir Roy Fielding termasuk dalam tesisnya, yang didasarkan pada http setelah semua.

Tapi dia memang berbicara tentang "transfer negara representasional" sebagai mesin negara, dengan tautan pindah ke negara berikutnya. Dengan cara ini, dokumen (representasi) melacak status klien, alih-alih server harus melakukannya. Dengan cara ini, tidak ada status klien, hanya status yang menghubungkan Anda.

Saya sudah memikirkan hal ini, dan menurut saya masuk akal bahwa untuk membuat server memproses sesuatu untuk Anda, ketika Anda mengunggah, server akan secara otomatis membuat sumber daya terkait, dan memberi Anda tautan ke mereka (pada kenyataannya, itu tidak akan tidak perlu secara otomatis membuat mereka: itu hanya bisa memberi tahu Anda tautan, dan itu hanya membuat mereka ketika dan jika Anda mengikuti mereka - penciptaan malas). Dan juga memberi Anda tautan untuk membuat sumber daya terkait baru - sumber daya terkait memiliki URI yang sama tetapi lebih lama (menambahkan akhiran). Sebagai contoh:

  1. Anda mengunggah ( POST ) representasi konsep transaksi dengan semua informasi. Ini terlihat seperti panggilan RPC, tetapi benar-benar menciptakan "sumber daya transaksi yang diusulkan". misalnya URI: /transaction Gangguan akan menyebabkan beberapa sumber daya tersebut dibuat, masing-masing dengan URI yang berbeda.
  2. Respons server menyatakan URI sumber daya yang dibuat, perwakilannya - ini mencakup tautan ( URI ) untuk membuat sumber daya terkait "sumber daya transaksi berkomitmen" baru. Sumber daya terkait lainnya adalah tautan untuk menghapus transaksi yang diajukan. Ini adalah status dalam state-machine, yang dapat diikuti oleh klien. Secara logis, ini adalah bagian dari sumber daya yang telah dibuat di server, di luar informasi yang diberikan klien. misalnya URI: /transaction/1234/proposed, /transaction/1234/committed
  3. Anda POST ke tautan untuk membuat "sumber daya transaksi berkomitmen" , yang menciptakan sumber daya itu, mengubah keadaan server (saldo kedua akun) **. Sesuai sifatnya, sumber daya ini hanya dapat dibuat satu kali, dan tidak dapat diperbarui. Karena itu, gangguan yang melakukan banyak transaksi tidak dapat terjadi.
  4. Anda dapat MENDAPATKAN kedua sumber daya itu, untuk melihat keadaan mereka. Dengan asumsi bahwa POST dapat mengubah sumber daya lain, proposal sekarang akan ditandai sebagai "berkomitmen" (atau mungkin, tidak tersedia sama sekali).

Ini mirip dengan cara laman web beroperasi, dengan laman web akhir mengatakan, "Anda yakin ingin melakukan ini?" Halaman web terakhir itu sendiri merupakan representasi dari keadaan transaksi, yang mencakup tautan untuk menuju ke negara berikutnya. Bukan hanya transaksi keuangan; juga (misalnya) pratinjau kemudian komit di wikipedia. Saya kira perbedaan dalam REST adalah bahwa setiap tahap dalam urutan negara memiliki nama eksplisit (URI-nya).

Dalam transaksi / penjualan dalam kehidupan nyata, seringkali ada dokumen fisik yang berbeda untuk tahapan transaksi yang berbeda (proposal, pesanan pembelian, tanda terima, dll). Bahkan lebih untuk membeli rumah, dengan penyelesaian dll.

OTOH Ini terasa seperti bermain dengan semantik bagi saya; Saya tidak nyaman dengan nominasi untuk mengubah kata kerja menjadi kata benda untuk membuatnya TETAP, "karena menggunakan kata benda (URI) alih-alih kata kerja (panggilan RPC)". yaitu kata benda "berkomitmen sumber daya transaksi" bukan kata kerja "melakukan transaksi ini". Saya kira salah satu keuntungan dari nominalisasi adalah Anda dapat merujuk ke sumber daya dengan nama, alih-alih perlu menentukannya dengan cara lain (seperti mempertahankan status sesi, sehingga Anda tahu apa transaksi "ini" adalah ...)

Tetapi pertanyaan penting adalah: Apa manfaat dari pendekatan ini? yaitu, dalam hal apa gaya REST ini lebih baik daripada gaya RPC? Apakah teknik yang bagus untuk halaman web juga membantu untuk memproses informasi, di luar toko / ambil / perbarui / hapus? Saya pikir manfaat utama REST adalah skalabilitas; satu aspek yang tidak perlu mempertahankan status klien secara eksplisit (tetapi membuatnya tersirat dalam URI sumber daya, dan status berikutnya sebagai tautan dalam perwakilannya). Dalam hal ini membantu. Mungkin ini membantu dalam layering / pipelining juga? OTOH hanya satu pengguna yang akan melihat transaksi spesifik mereka, sehingga tidak ada keuntungan dalam caching sehingga orang lain dapat membacanya, kemenangan besar untuk http.

13rn
sumber
Bisakah Anda jelaskan bagaimana "tidak perlu mempertahankan status klien" membantu skalabilitas? Skalabilitas seperti apa? Skalabilitas dalam arti apa?
jhegedus
11

Jika Anda mundur untuk merangkum diskusi di sini, cukup jelas bahwa REST tidak sesuai untuk banyak API, terutama ketika interaksi client-server inheren stateful, seperti halnya dengan transaksi non-sepele. Mengapa melompati semua simpulan yang disarankan, untuk klien dan server keduanya, agar mengikuti beberapa prinsip yang tidak sesuai dengan masalah? Prinsip yang lebih baik adalah memberi klien cara termudah, paling alami, dan produktif untuk menulis dengan aplikasi.

Singkatnya, jika Anda benar-benar melakukan banyak transaksi (tipe, bukan instance) dalam aplikasi Anda, Anda seharusnya tidak membuat RESTful API.

Peris
sumber
9
Benar, tetapi apa yang harus menjadi alternatif jika arsitektur layanan mikro terdistribusi?
Vitamon
11

Saya telah menjauh dari topik ini selama 10 tahun. Kembali, saya tidak percaya agama yang menyamar sebagai ilmu yang Anda masuki ketika Anda google + dapat diandalkan. Kebingungan itu bersifat mitos.

Saya akan membagi pertanyaan luas ini menjadi tiga:

  • Layanan hilir. Layanan web apa pun yang Anda kembangkan akan memiliki layanan hilir yang Anda gunakan, dan sintaks transaksinya Anda tidak punya pilihan selain mengikuti. Anda harus mencoba dan menyembunyikan semua ini dari pengguna layanan Anda, dan memastikan semua bagian dari operasi Anda berhasil atau gagal sebagai sebuah kelompok, kemudian mengembalikan hasil ini kepada pengguna Anda.
  • Layanan Anda Klien menginginkan hasil yang tidak ambigu untuk panggilan layanan web, dan pola REST yang biasa yaitu membuat POST, PUT, atau HAPUS meminta langsung pada sumber daya substantif yang membuat saya merasa miskin, dan mudah diperbaiki, cara memberikan kepastian ini. Jika Anda peduli akan keandalan, Anda perlu mengidentifikasi permintaan tindakan. Id ini bisa menjadi panduan yang dibuat pada klien, atau nilai seed dari DB relasional di server, tidak masalah. Untuk ID yang dihasilkan server, gunakan respons-permintaan 'preflight' untuk bertukar id tindakan. Jika permintaan ini gagal atau setengah berhasil, tidak ada masalah, klien hanya mengulangi permintaan itu. Id yang tidak digunakan tidak membahayakan.

    Ini penting karena memungkinkan semua permintaan berikutnya sepenuhnya idempoten, dalam arti jika mereka diulangi kali mereka mengembalikan hasil yang sama dan tidak menyebabkan apa-apa lagi terjadi. Server menyimpan semua respons terhadap id tindakan, dan jika ia melihat permintaan yang sama, ia mengulangi respons yang sama. Perawatan pola yang lebih lengkap ada di google doc ini . Dokumen ini menyarankan implementasi yang, saya percaya (!), Secara luas mengikuti prinsip-prinsip REST. Para ahli pasti akan memberi tahu saya bagaimana hal itu melanggar orang lain. Pola ini dapat digunakan untuk setiap panggilan tidak aman ke layanan web Anda, terlepas dari apakah ada transaksi hilir yang terlibat.
  • Integrasi layanan Anda ke dalam "transaksi" yang dikendalikan oleh layanan hulu. Dalam konteks layanan web, transaksi ACID penuh dianggap biasanya tidak sepadan dengan usaha, tetapi Anda dapat sangat membantu konsumen layanan Anda dengan memberikan tautan batal dan / atau mengkonfirmasi tautan dalam respons konfirmasi Anda, dan dengan demikian mencapai transaksi dengan kompensasi .

Kebutuhan Anda sangat mendasar. Jangan biarkan orang mengatakan solusi Anda tidak halal. Nilai arsitektur mereka berdasarkan seberapa baik, dan seberapa sederhana, mereka mengatasi masalah Anda.

bbsimonbb
sumber
9

Anda harus melempar jenis "id transaksi" Anda sendiri dari manajemen tx. Jadi itu akan menjadi 4 panggilan:

http://service/transaction (some sort of tx request)
http://service/bankaccount/bob (give tx id)
http://service/bankaccount/john (give tx id)
http://service/transaction (request to commit)

Anda harus menangani penyimpanan tindakan dalam DB (jika memuat seimbang) atau dalam memori atau semacamnya, kemudian menangani komit, kembalikan, batas waktu.

Bukan hari yang tenang di taman.

Perangkat LunakJedi
sumber
4
Saya pikir ini bukan ilustrasi yang bagus. Anda hanya memerlukan dua langkah: Buat transaksi (buat transaksi dalam status "menunggu") dan Transaksi komit (komit jika tidak dikomit, dan pindahkan sumber daya ke status berkomitmen atau putar-balik).
Jon Watte
2

Saya pikir dalam hal ini benar-benar dapat diterima untuk mematahkan teori murni REST dalam situasi ini. Bagaimanapun, saya tidak berpikir ada sesuatu yang sebenarnya di REST yang mengatakan Anda tidak dapat menyentuh objek dependen dalam kasus bisnis yang memerlukannya.

Saya benar-benar berpikir itu tidak sebanding dengan lingkaran ekstra yang akan Anda lompati untuk membuat manajer transaksi khusus, ketika Anda bisa memanfaatkan database untuk melakukannya.

Toby Hede
sumber
2

Pertama-tama, mentransfer uang adalah hal yang tidak dapat Anda lakukan dalam satu panggilan sumber daya. Tindakan yang ingin Anda lakukan adalah mengirim uang. Jadi, Anda menambahkan sumber daya pengiriman uang ke akun pengirim.

POST: accounts/alice, new Transfer {target:"BOB", abmount:100, currency:"CHF"}.

Selesai Anda tidak perlu tahu bahwa ini adalah transaksi yang harus atom dll. Anda hanya mentransfer uang alias. kirim uang dari A ke B.


Tetapi untuk kasus yang jarang terjadi di sini solusi umum:

Jika Anda ingin melakukan sesuatu yang sangat kompleks yang melibatkan banyak sumber daya dalam konteks yang ditentukan dengan banyak batasan yang benar-benar melintasi penghalang apa vs. mengapa (pengetahuan bisnis vs implementasi), Anda perlu mentransfer status. Karena REST seharusnya tidak memiliki kewarganegaraan, Anda sebagai klien harus mentransfer keadaan sekitar.

Jika Anda mentransfer status Anda perlu menyembunyikan informasi di dalam dari klien. Klien seharusnya tidak mengetahui informasi internal yang hanya dibutuhkan oleh implementasi tetapi tidak membawa informasi yang relevan dalam hal bisnis. Jika informasi itu tidak memiliki nilai bisnis, negara harus dienkripsi dan metafora seperti token, pass atau sesuatu perlu digunakan.

Dengan cara ini seseorang dapat melewati keadaan internal sekitar dan menggunakan enkripsi dan menandatangani sistem masih aman dan sehat. Menemukan abstraksi yang tepat untuk klien mengapa ia memberikan informasi negara adalah sesuatu yang sesuai dengan desain dan arsitektur.


Solusi nyata:

Ingat REST sedang berbicara HTTP dan HTTP hadir dengan konsep menggunakan cookies. Cookie itu sering dilupakan ketika orang berbicara tentang REST API dan alur kerja serta interaksi yang mencakup banyak sumber daya atau permintaan.

Ingat apa yang tertulis di Wikipedia tentang cookie HTTP:

Cookie dirancang untuk menjadi mekanisme yang andal bagi situs web untuk mengingat informasi stateful (seperti item dalam keranjang belanja) atau untuk merekam aktivitas penelusuran pengguna (termasuk mengklik tombol tertentu, masuk, atau merekam halaman mana yang dikunjungi oleh pengguna sejauh ini. kembali sebagai bulan atau tahun yang lalu).

Jadi pada dasarnya jika Anda perlu menyampaikan status, gunakan cookie. Ini dirancang untuk alasan yang persis sama, ini adalah HTTP dan karena itu kompatibel dengan REST by design :).


Solusi yang lebih baik:

Jika Anda berbicara tentang klien yang melakukan alur kerja yang melibatkan beberapa permintaan, Anda biasanya berbicara tentang protokol. Setiap bentuk protokol dilengkapi dengan serangkaian prasyarat untuk setiap langkah potensial seperti melakukan langkah A sebelum Anda dapat melakukan B.

Ini adalah protokol yang alami tetapi mengekspos kepada klien membuat segalanya lebih kompleks. Untuk menghindarinya, pikirkan saja apa yang kita lakukan ketika kita harus melakukan interaksi yang kompleks dan hal-hal di dunia nyata .... Kami menggunakan Agen.

Menggunakan metafora Agen, Anda dapat memberikan sumber daya yang dapat melakukan semua langkah yang diperlukan untuk Anda dan menyimpan tugas / instruksi aktual yang ditindaklanjuti dalam daftar (sehingga kami dapat menggunakan POST pada agen atau 'agen').

Contoh kompleks:

Membeli rumah:

Anda perlu membuktikan kredibilitas Anda (seperti memberikan catatan catatan polisi Anda), Anda perlu memastikan perincian keuangan, Anda perlu membeli rumah yang sebenarnya menggunakan pengacara dan pihak ketiga yang dipercaya menyimpan dana, memverifikasi bahwa rumah itu sekarang milik Anda dan tambahkan barang yang dibeli ke catatan pajak Anda dll. (seperti contohnya, beberapa langkah mungkin salah atau apa pun).

Langkah-langkah ini mungkin memakan waktu beberapa hari untuk diselesaikan, beberapa dapat dilakukan secara paralel dll.

Untuk melakukan ini, Anda hanya memberi agen rumah tugas beli seperti:

POST: agency.com/ { task: "buy house", target:"link:toHouse", credibilities:"IamMe"}.

Selesai Agensi mengirimkan kembali referensi kepada Anda yang dapat Anda gunakan untuk melihat dan melacak status pekerjaan ini dan sisanya dilakukan secara otomatis oleh agen agensi.

Pikirkan tentang pelacak bug misalnya. Pada dasarnya Anda melaporkan bug dan dapat menggunakan id bug untuk memeriksa apa yang terjadi. Anda bahkan dapat menggunakan layanan untuk mendengarkan perubahan sumber daya ini. Misi Selesai.

Martin Kersten
sumber
1

Anda tidak boleh menggunakan transaksi sisi server di REST.

Salah satu kendala REST:

Tanpa kewarganegaraan

Komunikasi klien-server lebih lanjut dibatasi oleh tidak ada konteks klien yang disimpan di server antara permintaan. Setiap permintaan dari klien mana pun mengandung semua informasi yang diperlukan untuk melayani permintaan tersebut, dan setiap sesi sesi diadakan di klien.

Satu-satunya cara RESTful adalah dengan membuat transaksi redo log dan memasukkannya ke dalam status klien. Dengan permintaan klien mengirim redo log dan server mengulang transaksi dan

  1. mengembalikan transaksi tetapi memberikan redo log transaksi baru (satu langkah lebih jauh)
  2. atau akhirnya menyelesaikan transaksi.

Tetapi mungkin lebih mudah untuk menggunakan teknologi berbasis sesi server yang mendukung transaksi sisi server.

bebbo
sumber
Kutipan ini dari entri REST wikipedia. Apakah ini sumber asli atau apakah wikipedia mendapatkannya dari suatu tempat? Siapa yang mengatakan apa konteks klien dan apa konteks server?
bbsimonbb
1

Saya percaya itu akan menjadi kasus menggunakan pengidentifikasi unik yang dihasilkan pada klien untuk memastikan bahwa cegukan koneksi tidak menyiratkan dalam duplikasi yang disimpan oleh API.

Saya pikir menggunakan bidang GUID yang dibuat klien bersama dengan objek transfer dan memastikan bahwa GUID yang sama tidak dimasukkan kembali lagi akan menjadi solusi yang lebih sederhana untuk masalah transfer bank.

Tidak tahu tentang skenario yang lebih kompleks, seperti pemesanan tiket pesawat ganda atau arsitektur mikro.

Saya menemukan sebuah makalah tentang subjek, yang menghubungkan pengalaman berurusan dengan atomicity transaksi di layanan tenang .

Eduardo Rolim
sumber
0

Dalam kasus sederhana (tanpa sumber daya terdistribusi), Anda dapat mempertimbangkan transaksi sebagai sumber daya, di mana tindakan menciptakannya mencapai tujuan akhir.

Jadi, untuk mentransfer antar <url-base>/account/adan <url-base>/account/b, Anda dapat memposting yang berikut ke <url-base>/transfer.

<transfer>
    <dari> <url-base> / akun / a </dari>
    <to> <url-base> / akun / b </to>
    <amount> 50 </amount>
</transfer>

Ini akan membuat sumber transfer baru dan mengembalikan url baru transfer - misalnya <url-base>/transfer/256.

Pada saat pos berhasil, maka, transaksi 'nyata' dilakukan di server, dan jumlah dihapus dari satu akun dan ditambahkan ke yang lain.

Namun, ini tidak mencakup transaksi yang didistribusikan (jika, katakanlah 'a' diadakan di satu bank di belakang satu layanan, dan 'b' diadakan di bank lain di belakang layanan lain) - selain untuk mengatakan "coba untuk frase semua operasi dengan cara yang tidak memerlukan transaksi terdistribusi ".

Phasmal
sumber
2
Jika Anda tidak dapat "mengucapkan semua operasi dengan cara yang tidak memerlukan transaksi terdistribusi", maka Anda benar-benar membutuhkan komitmen dua fase. Gagasan terbaik yang dapat saya temukan untuk menerapkan komit dua fase pada REST adalah rest.blueoxen.net/cgi-bin/wiki.pl?TwoPhaseCommit , yang penting tidak mengacaukan namespace URL dan memungkinkan dua fase komit untuk berlapis membersihkan semantik SISA.
Phasmal
3
Masalah lain dengan saran ini adalah bahwa, jika cegukan cache dan POST dua kali, Anda mendapatkan dua transfer.
Jon Watte
Benar, dalam hal ini Anda harus memiliki proses dua langkah - buat sumber daya "transfer" dengan URL unik lalu tambahkan detail transfer ke dalamnya sebagai bagian dari komit (dua bagian seperti yang disebutkan dalam jawaban lain). Tentu saja, ini kemudian dapat dirumuskan sebagai menciptakan sumber daya "transaksi" kemudian menambahkan operasi "transfer" ke dalamnya.
Phasmal
-3

Saya kira Anda dapat memasukkan TAN di URL / sumber daya:

  1. PUT / transaksi untuk mendapatkan ID (mis. "1")
  2. [PUT, DAPATKAN, POST, apa pun] / 1 / akun / bob
  3. [PUT, DAPATKAN, POST, apa pun] / 1 / akun / tagihan
  4. HAPUS / transaksi dengan ID 1

Hanya sebuah ide.

Sampai
sumber
Saya melihat dua masalah dengan pendekatan ini: 1) Ini menyiratkan Anda tidak dapat mengakses sumber daya di luar transaksi (meskipun mungkin ini bukan masalah besar). 2) Sejauh ini tidak ada jawaban yang menyentuh fakta bahwa server tidak lagi tanpa kewarganegaraan, meskipun saya curiga tidak ada yang dapat dilakukan mengenai hal itu.
Gili
Nah, / 1 / akun / bob dan / akun / bob hanyalah dua sumber yang berbeda. :) Dan RE: stateless, ini menyiratkan bahwa sumber daya selalu tersedia dan tidak bergantung pada permintaan sebelumnya. Karena Anda meminta transaksi, ya bukan itu masalahnya. Tetapi sekali lagi, Anda menginginkan transaksi.
Hingga
1
Jika klien harus merakit URI, maka API Anda tidak TETAP.
aehlke
1
Aku tidak bisa mengerti kalian, sungguh! Jika Anda memperlakukan transaksi sebagai sumber daya (seperti dalam contoh di atas), Anda cukup berhenti memperlakukan transaksi dalam pengertian klasik dan menggunakannya dalam "cara REST yang tepat" yang selanjutnya menyederhanakan pemrograman proses transaksional. Misalnya Anda dapat memasukkan href ke transaksi dalam respons Anda untuk berpindah di lingkungan sisi server terdistribusi, itu masih tanpa kewarganegaraan (itu hanya sumber daya, bukan?) Dan Anda dapat menerapkan mekanisme transaksi yang sebenarnya pula Anda inginkan (bagaimana jika Anda tidak memiliki DB di belakang?)
Matthias Hryniszak
1
Salah satu cara atau yang lain jika Anda hanya berhenti berpikir SQL / SOAP dan mulai berpikir HTTP (seperti browser tidak) semuanya menjadi sederhana
Matthias Hryniszak