2重リクエスト完全攻略HANDBOOK / Double Request Handbook
by
ShoheiMitani
Link
Embed
Share
Beginning
This slide
Copy link URL
Copy link URL
Copy iframe embed code
Copy iframe embed code
Copy javascript embed code
Copy javascript embed code
Share
Tweet
Share
Tweet
Slide 1
Slide 1 text
2ॏϦΫΤετશ߈ུHANDBOOK Shohei Mitani @ εϚʔτόϯΫ
Slide 2
Slide 2 text
2ॏϦΫΤετ • ޡͬͯෳճಉ͡ϦΫΤετ͕ૹΒΕɺॏෳͯ͠ॲཧ͕ߦΘΕͯ͠·͏͜ͱ • αϒϛοτϘλϯ͕2ճԡ͞Εͨ • ొը໘͕Ϧϩʔυ͞Εͨ • ֎෦αʔϏε͔Βෳճಉ͡σʔλ͕ૹΒΕͨ • όον͕2ճ࣮ߦ͞Εͨ • 2ॏαϒϛοτͱ͍͏ݴ͍ํ͋Δ͕ɺWebϒϥβҎ֎ʹى͜Γ͏Δ Λѻ͍͍ͨͷͰ2ॏϦΫΤετͱݺͿ • 2ճҎ্ϦΫΤετ͢ΔଟॏϦΫΤετ2ॏϦΫΤετͱݺͿ͜ͱʹ͢Δ
Slide 3
Slide 3 text
͠2ॏϦΫΤετ͕ൃੜͨ͠Β…?? • ܝࣔ൘ʹಉ͡༰͕2ճߘ͞ΕΔ... • ಉ͕͡2ճߪೖ͞Εͯɺ2ॏͰߴ͕ݮΔ͜ͱʹ… • ܾࡁ / ૹۚ / ༧ / ग़ / ථ / ใु༩ / ਃ / etc… • ѱ༻͞Εͯෆਖ਼߈ܸΛड͚ΔηΩϡϦςΟϗʔϧʹ… • Etc…
Slide 4
Slide 4 text
2ॏϦΫΤετͷରࡦҙ֎ͱ͍͠ • ΫϥΠΞϯτͰ੍ޚ͢Ε͍͍Μ͡Όͳ͍ͷ͔ʁ • ΫϦοΫ࿈ଧ / ϖʔδ࠶ಡΈࠐΈ / Δˠ࠶ૹ৴ͳͲɺͲ͜·ͰରԠͰ͖Δʁ • ϒϥβͷσϕϩούʔπʔϧͰૢ࡞͞ΕͨΒʁ • ෳλϒʗෳ͔Βಉ࣌ʹૢ࡞͞Εͨ߹ʹͰ͖Δରࡦʁ • ֎෦αʔϏε͔Βͷࣗಈ࠶ૹͳͲɺΫϥΠΞϯτଆΛ੍ޚͰ͖ͳ͍߹ʹʁ • όοΫΤϯυͰςʔϒϧઃܭΛ্ख͘ΕେৎͰ͠ΐ • ϢχʔΫ੍͕͚ͭΒΕͳ͔ͬͨΓɺϩοΫ͕औΕͳ͍ঢ়گ͋Δ • ҙਤͨ͠ෳճͷૢ࡞ͱɺࣄނతʹൃੜͨ͠2ॏϦΫΤετΛผͰ͖Δʁ
Slide 5
Slide 5 text
Θ͟Θ͟Kaigi on RailsͰൃද͢Δ΄Ͳʁ • WebͰݕࡧͯ͠ग़ͯ͘Δํ๏WebϒϥβΛલఏͱ ͯ͠ͷ͕ଟ͍ • ʮJavaScritptͰʙʯʮ֬ೝμΠΞϩάग़ͯ͠ʙʯ • ʮઈରʹೋॏαϒϛοτΛڐ͞ͳ͍༑ͷձʯͷϒϩάΑ ͘·ͱ·ͬͯΔ • ݱ࣮ͷΞϓϦέʔγϣϯෳࡶͰ৭ʑͳέʔε͕͋Δ • ຖճɺରࡦΛௐͨΓಠࣗʹฤΈग़͢͜ͱʹർΕͨ • ͜Ε͚ͩݟ͓͚ͯେମΧόʔ͞ΕͯΔͷΛ࡞Γ͍ͨ https://qiita.com/unmelt/items/fb1eff5a2d9bc4da1f7e
Slide 6
Slide 6 text
ࠓͷൃදςʔϚ • ୭ʹͱͬͯۙͰॏཁͳ2ॏϦΫΤετʹ·ͳ͍͍ͯ͘ੈքΛ࡞Δ • 2ॏϦΫΤετͷͷཧղ • ༷ʑͳ2ॏϦΫΤετରࡦͷཧղ • ϢʔεέʔεʹԠͨ͡ϕετϓϥΫςΟεͷ୳ࡧ • ྩ7࣌ͰͷใΛ·ͱΊͨHANDBOOKΛఏڙ • ۀͰૺ۰ͨ࣌͠ʹݟฦͤΔࢿྉͱͳΕ͍ • ଞʹ͜͏͍͏ͷ͋ΔΑʂͬͯํ๏͋Εڭ͍͑ͯͩ͘͞🙌 • ݸʑͷରࡦͷৄࡉׂѪ͠·͢
Slide 7
Slide 7 text
ࣗݾհ ࡾ୩ ণฏ Έͨʹ ͠ΐ͏͍ εϚʔτόϯΫ Engineering Manager / Software Engineer • SIer → Fablic → ָఱ → εϚʔτόϯΫ • ΤϯδχΞྺ11ɺRailsྺ7 • Welcome Fintech Community ӡӦ
Slide 8
Slide 8 text
ৗͰ͍ͬͯΔαʔϏεͷཪଆΛެ։Մೳͳܗʹམͱ͠ࠐΜͰൃද͢Δͷ͕͖ builderscon 2024 YAPC::Hiroshima 2024 YAPC::Fukuoka 2025 eKYC Χʔυܾࡁ ڝഅ x ػցֶश χον͗ͯ͢ڵຯ࣋ͨΕͳ͍? ެ։͢Δͱڝ߹༏Ґੑࣦ͏? ڪΕͣൃද͢Δ͜ͱͰಘΒΕΔ͜ͱଟ͍
Slide 9
Slide 9 text
ࠓͬͪ͜ͷ Kaigi on Rails 2022 Kaigi on Rails 2021 Kaigi on Rails 2023 ։ൃݱͰͷ࣮ઓΛநԽɾ൚༻తֶͯ͠ͼʹม͍͑ͯ͘׆ಈ͖ ࢹ ঢ়ଶཧ ςʔϒϧఆٛมߋ
Slide 10
Slide 10 text
2ॏϦΫΤετͷޚࡦ
Slide 11
Slide 11 text
લఏ͢Γ߹Θͤʙհ͢Δޚࡦͷείʔϓʙ • POST / PUT / DELETEͷߋ৽ܥૢ࡞Λத৺ʹѻ͏ʢGETͷԠ༻Մʣ • ૹ৴ऀଆʹѱҙͳ͍͕ࣄނతʹ2ॏϦΫΤετ͕ൃੜ͢Δͷޚࡦ • αϒϛοτϘλϯ͕ԿԡͤΔͷ࣮࿙Ε • όοΫΤϯυͰͷλΠϜΞτʹΑΓɺΫϥΠΞϯτ͔Β࠶ૢ࡞͕Ͱ͖Δέʔε • ૹ৴ऀଆ͕ѱҙΛ࣋ͬͯ2ॏϦΫΤετΛߦ͏Α͏ͳͷޚࡦ • ੬ऑੑΛಥ͍ͨϦϓϨΠ߈ܸ / ෳͰͷಉ࣌ૢ࡞ • ༷ͱͯ͠ಉ͡༰ͷૢ࡞͕ڐ༰͞Ε͍ͯΔέʔεͱͷ۠ผ͢Δํ๏ • ಉҰͷߪೖ / ࿈ߘ
Slide 12
Slide 12 text
ෳͷޚͰߟ͑Δ 📱 🐟 ΫϥΠΞϯτଆ ޚࡦͷҹ όοΫΤϯυଆ ޚࡦͷҹ
Slide 13
Slide 13 text
ᶃ αϒϛοτϘλϯͷ੍ޚ ᶄ Post-Redirect-Get (PRG) ύλʔϯ ᶅ ഉଞ੍ޚ • Ϧιʔεͷ൵؍ϩοΫ • FIFOʹΑΔॱং੍ޚ • ΞυόΠβϦʔϩοΫ ᶆ ςʔϒϧઃܭ • ঢ়ଶભҠͷϧʔϧԽ • ϢχʔΫ੍ ࠓհ͢Δޚࡦͨͪ ᶇ ϨʔτϦϛοτ ᶈ APIΩϟογϡ ᶉ Idempotency-Keyϔομ ᶊ ETag ʴ If-Match ᶋ ϫϯλΠϜτʔΫϯ
Slide 14
Slide 14 text
ᶃ αϒϛοτϘλϯͷ੍ޚ • ࠷جຊతͰ࠷ॳʹΔͰ͋Δ2ॏϦΫΤετ Λ͙ํ๏ • ϘλϯΛԡͨ͠Βྃ͢Δ·Ͱඇ׆ੑԽ͢Δ • Βͳ͍ͱ͍͏બࢶͳͦ͞͏ʢ?ʣ • ॲཧঢ়ଶΛอ͓͖࣋ͯ͠ɺॲཧதʹૢ࡞͞Εͨ ߹ʹϝοηʔδΛදࣔ͢Δ͜ͱՄೳ 📱
Slide 15
Slide 15 text
• ϒϥβͷϦϩʔυʹΑΔ2ॏϦΫΤετΛ͙ํ๏ • POSTϦΫΤετͷྃ࣌ɺHTMLΛฦ٫͢ΔͷͰͳ ͘ɺ݁ՌදࣔϖʔδϦμΠϨΫτ͢ΔϨεϙϯεΛฦ͢ • ॲཧྃޙʹϒϥβͰϦϩʔυΛͯ͠ɺϦμΠϨΫτઌ ͷGETॲཧͱͳΔͨΊɺݩͷPOSTॲཧͷ2ॏϦΫΤετ͕ى ͖ͳ͍ • ΔϘλϯͰલը໘ʹ͔ͬͯΒɺ͏ҰαϒϛοτϘλ ϯΛԡ͞ΕΔέʔεʹແྗͳͷͰɺผରࡦ͕ඞཁ ᶄ Post-Redirect-Get (PRG) ύλʔϯ ΫϥΠΞϯτ αʔόʔ POST REDIRECT GETʢ݁Ռը໘ʣ HTML ϦϩʔυʢGETʣ 🐟
Slide 16
Slide 16 text
ᶅ ഉଞ੍ޚ • ͋ΔϓϩηεͷΈ͕ϦιʔεͷΞΫηεݖΛಠ͢Δ͜ͱͰɺ ಉ࣌ʹૢ࡞Ͱ͖ΔϓϩηεΛҰͭʹ੍ݶ͢ΔΈ • 2ॏϦΫΤετ͕ൃੜͯ͠αʔόʔଆͰ҆શʹॲཧͯ͠ޚ ͢Δํ๏ • ಉ࣌ʹಉ͡ϦιʔεΛૢ࡞͢Δͱσʔλͷෆ߹͕ى͖͍͢ • ϩετΞοϓσʔτͷ • ಉ࣮࣌ߦΛ͙͜ͱͰɺॲཧ෦Ͱߟྀ͠ͳ͚ΕͳΒͳ͍͜ͱ͕ ݮΒͤΔ 🐟 Table READ BLOCK READ
Slide 17
Slide 17 text
ᶅ ഉଞ੍ޚʙϦιʔεͷ൵؍తϩοΫʙ • RDBΛར༻͍ͯ͠Δ߹ʹ࠷؆୯ʹར༻Ͱ͖Δͷ൵؍తϩοΫ • User. fi nd(1).with_lock { … } • ૢ࡞ରʹରͯ͠ɺదͳϩοΫΛऔΕΔϦιʔε͕ଘࡏ͠ͳ͍߹͋Δ • ΞυόΠβϦʔϩοΫͷར༻ʢMySQL: GET _LOCK / PostgreSQL: pg_advisory_lockʣ • ActiveRecord::Base.connection.get_advisory_lock(“UserID#{user_id}:Payment”) • ϩοΫઐ༻ͷςʔϒϧRedisΛ͏ߟ͑ΒΕΔ • ඇಉظతʹॲཧΛͯ͠ྑ͍߹ʹFIFOΩϡʔΛ͏͜ͱ • FIFOʢFirst-in, First-outʣͷΩϡʔΛ͏͜ͱͰɺΩϡʔ୯ҐͰॱ൪ʹॲཧ͕ߦΘΕΔ ͨΊɺϩοΫΛऔಘͨ࣌͠ͱಉ͡Α͏ʹഉଞ੍ޚ͞ΕΔ 🐟
Slide 18
Slide 18 text
ᶅ ഉଞ੍ޚʙҙʙ • ഉଞ੍ޚಉ࣌ʹૢ࡞͞ΕΔ͜ͱΛ͍Ͱ͍Δ͚ͩͳͷͰɺϩοΫղ์͞Εͨ ޙͷॲཧͷରԠผ్ߟ͑Δඞཁ͕͋Δ • ଈ࣌Τϥʔʹ͢ΔͳΒ : User. fi nd(1).with_lock(“FOR UPDATE NOWAIT”) { … } • ଈ࠲Τϥʔɺಉ࣌ʹϩοΫΛऔಘͨ͠߹ʹݶΔͷͰɺλΠϜϥά͕͋ͬͯ2ॏϦΫ Τετ͕དྷͨ࣌ͷ͜ͱΛߟ͑Δඞཁ͕͋Δ • ϩοΫͷऔಘൣғʹҙ͕ඞཁ • 2ॏϦΫΤετΛ͍͗ͨAPIҎ֎ͰϩοΫղ์͕ͪൃੜ͠ɺϨεϙϯελΠϜ͕ѱ Խ͢Δͷ͋Δ͋Δͳ 🐟
Slide 19
Slide 19 text
ᶆ ςʔϒϧઃܭ • 2ॏϦΫΤετ͕ൃੜͯ͠σʔλͷ߹ੑΛอͯΔΑ͏ςʔϒϧઃܭ͓ͯ͘͠ ͜ͱͰޚ͢Δํ๏ • ഉଞ੍ޚͱҟͳΓɺಉ࣌ʹϦΫΤετ͕དྷͳ͍έʔεͰ͋ͬͯɺ͋Δ͖σʔλͷ ͕࢟อͨΕΔΑ͏ʹ͢Δ • ςʔϒϧઃܭͷํ๏ଟछଟ༷ʹ͋ΓɺશͯΛհ͢Δ͜ͱͰ͖ͳ͍ͷͰɺ ݸਓతʹΑ͘͏ํ๏Λ2ͭհ 🐟
Slide 20
Slide 20 text
ᶆ ςʔϒϧઃܭʙঢ়ଶભҠͷϧʔϧԽʙ • ঢ়ଶؒͷભҠϧʔϧΛఆٛ͢Δ͜ͱͰɺ2ॏϦΫΤετ Λड͚औͬͨࡍʹঢ়ଶભҠΤϥʔΛൃੜͤ͞Δ • ӈͷྫͩͱɺจঢ়ଶͱ͍͏ENUMͷΧϥϜʹঢ়ଶભ ҠͷϧʔϧΛఆٛ͢Δ • ʮΩϟϯηϧঢ়ଶจঢ়ଶ͔Β͔͠ભҠͰ͖ͳ͍ʯ • ʮٻঢ়ଶจঢ়ଶ͔Β͔͠ભҠͰ͖ͳ͍ʯ • ʮൃૹঢ়ଶٻঢ়ଶ͔Β͔͠ભҠͰ͖ͳ͍ʯ • RailsͩͱAASMͷgem͕͋Δ 🐟
Slide 21
Slide 21 text
ᶆ ςʔϒϧઃܭʙϢχʔΫ੍ʙ • ϢχʔΫ੍Λ͚ͭΔ͜ͱͰɺ2ॏϦΫΤετ Λड͚औͬͨࡍʹঢ়ଶભҠΤϥʔΛൃੜͤ͞Δ • ӈͷྫͩͱɺจͷঢ়ଶຖʹςʔϒϧΛׂ ͠ɺจIDʹϢχʔΫ੍ʢUQʣΛ͚ͭΔ • ΠϛϡʔλϒϧσʔλϞσϧ • https://scrapbox.io/kawasima/ΠϛϡʔλϒϧσʔλϞσϧ 🐟
Slide 22
Slide 22 text
ঢ়ଶભҠͷϧʔϧԽ vs ϢχʔΫ੍ • ঢ়ଶભҠͷϧʔϧԽͰɺϩετΞοϓσʔτͷҙ͕ඞཁ • ผτϥϯβΫγϣϯͷ༰͕ಡΈऔΕͳ͍ͨΊɺӈਤͩͱٻ → ٻͷঢ়ଶมߋΛNGͱ͢ΔΑ͏ͳϧʔϧ͢Γൈ͚ΒΕΔ • τϥϯβΫγϣϯΛషΔ߹ʹഉଞ੍ޚͱηοτͰߟ͑Δ͖ • ޙ͔Βॲཧͨ͠༰Ͱ্ॻ͖ͯ͠ͳ͍༷Ͱ͋Εෆཁ • ϢχʔΫ੍ͷ߹ɺτϥϯβΫγϣϯΛίϛοτͨ͠λΠϛ ϯάͰΤϥʔ͕ൃੜ͢ΔͨΊɺϩοΫෆཁͳར͕͋Δ • σʔλϕʔεͷ੍ศར TRN1 TRN2 *% ঢ়ଶ จ ࣌ ࣌ Table Table Table *% ঢ়ଶ ٻ ࣌ ࣌ *% ঢ়ଶ ٻ ࣌ ࣌ 🐟
Slide 23
Slide 23 text
ᶇ ϨʔτϦϛοτ • ഉଞ੍ޚ / ঢ়ଶભҠͷϧʔϧԽ / ϢχʔΫ੍͍ͣΕΞϓϦέʔγϣϯͰσʔλ ͷ߹ੑΛอͭͨΊͷΞϓϩʔν • ΫϨδοτΧʔυʹਃ͠ࠐΉͳͲɺݱ࣮ͱͯ͠ࢦఆظؒʹෳૢ࡞͞Εͳ͍ͱ্ׂ༷ ΓΕΔػೳͰ͋ΕɺΑΓ্ҐϨΠϠʔͰͷޚ͕Մೳ • ϨʔτϦϛοτ : γεςϜͷաͳෛՙΛ͙ͨΊʹɺҰఆظؒʹॲཧͰ͖Δ ϦΫΤεττϥϑΟοΫͷྔΛ੍ݶ͢Δख๏ͷ͜ͱ • ϢʔβʔIDͳͲΛΩʔʹAPIʹϨʔτϦϛοτΛಋೖ͠ɺҰఆظؒ1ճ͔͠ϦΫΤε τͰ͖ͳ͍Α͏ʹ͢Δ 🐟
Slide 24
Slide 24 text
ϨʔτϦϛοτͷϑϩʔ 📱ΫϥΠΞϯτ 🐟αʔόʔ ⚙*'/PU&YJTU ͷϩοΫ ߪೖঢ়ଶͷมߋ &UDʜ σʔλετΞ 🎁ߪೖྃ 🐟 1045QBZNFOUT nJUFN@JEJUFN@ 1BZNFOUJUFN $IFDL 63-1045QBZNFOUT *UFN*%JUFN@ 4BWF 63-1045QBZNFOUT *UFN*%JUFN@ 55-
Slide 25
Slide 25 text
ϨʔτϦϛοτͷϑϩʔ 📱ΫϥΠΞϯτ 🐟αʔόʔ σʔλετΞ 🐟 1045QBZNFOUT nJUFN@JEJUFN@ ❌'PSCJEEFO $IFDL 63-1045QBZNFOUT *UFN*%JUFN@ 💀ߪೖࣦഊ ⚙*'&YJTU$PVOU Τϥʔॲཧ
Slide 26
Slide 26 text
• Amazon API GatewayͳͲͷඪ४ػೳʢεϩοτϦϯάʣΛར༻͢Δ͜ͱՄೳ • εϩοτϦϯάͷద༻ൣғʢϦʔδϣϯ / APIΩʔ/ϝιουʣͷઃܭ࣍ୈ • ྫ: toB͚αʔϏεͷΫϥΠΞϯτຖʹAPI KeyΛൃߦ͠ɺͦͷKeyϨϕϧͰಛఆ ΤϯυϙΠϯτͷϦΫΤετΛ1ճʹߜΔͳͲ • ࡉ͔͍୯ҐͰ੍ޚ͕ඞཁͳ߹ࣗલߏங͢Δඞཁ͋Γ • rack-attack gem / throttling gem ͋ͨΓ͕ࢀߟʹͳΔ͔ • Rails 8͔Βඪ४ͰϨʔτϦϛοτͷػೳ͕ೖͬͨ ϨʔτϦϛοτͷิ 🐟
Slide 27
Slide 27 text
ᶈ APIΩϟογϡ • Ұड͚͚ͨϦΫΤετͷϨεϙϯεΛอଘ͓͍ͯͯ͠ɺಉҰϦΫΤετ͕ དྷͨ߹ʹΩϟογϡͨ͠ϨεϙϯεΛฦ٫͢Δ͜ͱͰႈੑΛ୲อ͢ΔΞ ϓϩʔν • ΫϥΠΞϯτଆ͔ΒݟΔͱ2ॏͰૹ৴ͨ͠ࡍɺͲͪΒޭѻ͍ͱͯ͠ϋϯυϦϯά Ͱ͖ΔʢϨʔτϦϛοτͱͷҧ͍ʣ • Amazon API GatewayͳͲͷػೳΛར༻͢Δ͜ͱʹΑΓɺΞϓϦέʔγϣϯͷ ֎ଆͰ2ॏϦΫΤετΛޚ͢Δ͜ͱ͕Մೳ 🐟
Slide 28
Slide 28 text
APIΩϟογϡͷϑϩʔ 📱ΫϥΠΞϯτ 🐟αʔόʔ ⚙*'/PU&YJTU ͷϩοΫ ߪೖঢ়ଶͷมߋ &UDʜ σʔλετΞ 🎁ߪೖྃ 🐟 1045QBZNFOUTJUFN@ 1BZNFOUJUFN $IFDL ,FZ1045QBZNFOUTJUFN@ 4BWF ,FZ1045QBZNFOUTJUFN@ 3FTQPOTF#PEZYYYY 55-
Slide 29
Slide 29 text
APIΩϟογϡͷϑϩʔ 📱ΫϥΠΞϯτ 🐟αʔόʔ ⚙*'&YJTU 3FTQPOTF#PEZͷऔಘ σʔλετΞ 🎁ߪೖྃ 🐟 1045QBZNFOUTJUFN@ 1BZNFOUJUFN DBDIFE $IFDL ,FZ1045QBZNFOUTJUFN@
Slide 30
Slide 30 text
• ΩϟογϡΛ͏͜ͱͷҰൠతͳࠔ͞ʹཱ͔ͪ͏ඞཁ͕͋Δ • ΩϟογϡͷKeyΛͲ͏͢Δ͔ʁ • ΩϟογϡͷTTLΛͲ͏͢Δ͔ʁ • ΩϟογϡͰ͖ΔαΠζͷݶք • GET·ͩ͠ɺPOSTܥͷAPIΛΩϟογϡͯ͠ྑ͍ͷ͔ʁ • Ωϟογϡ͕อଘ͞ΕΔ·Ͱͷؒʹൃੜ͢Δ2ॏϦΫΤετແྗ APIΩϟογϡͷิ 🐟
Slide 31
Slide 31 text
• ΫϥΠΞϯτ͕ϦΫΤετΛҰҙʹࣝผͰ͖ΔใʢIdempotency KeyʣΛ HTTPϔομʹ༩͢Δ͜ͱʹΑΓႈͳAPIΛߏங͢ΔΞϓϩʔν ᶉ Idempotency-Keyϔομ 🐟 📱 https://speakerdeck.com/ohbarye/safe-retry-with-idempotency-key-header https://speakerdeck.com/ohbarye/my-favorite-protocol-idempotency-key-header
Slide 32
Slide 32 text
Idempotency-Keyϔομͷϑϩʔ 📱ΫϥΠΞϯτ 🐟αʔόʔ ⚙*'/PU&YJTU ͷϩοΫ ߪೖঢ়ଶͷมߋ &UDʜ σʔλετΞ 🎁ߪೖྃ 1045QBZNFOUT nJUFN@JEJUFN@= )t*EFNQPUFODZ,FZYZ[u 1BZNFOUJUFN $IFDL ,FZYZ[ 4BWF ,FZYZ[ 3FTQPOTF#PEZYYYY 55- 🐟 📱 ,FZ࠾൪
Slide 33
Slide 33 text
Idempotency-Keyϔομͷϑϩʔ 📱ΫϥΠΞϯτ 🐟αʔόʔ ⚙*'&YJTU 3FTQPOTF#PEZͷऔಘ σʔλετΞ 🎁ߪೖྃ 1BZNFOUJUFN DBDIFE 🐟 📱 1045QBZNFOUT nJUFN@JEJUFN@= )t*EFNQPUFODZ,FZYZ[u ,FZ࠾൪ $IFDL ,FZYZ[
Slide 34
Slide 34 text
APIΩϟογϡ vs Idempotency-Keyϔομ • Idempotency KeyϔομAPIΩϟογϡΑΓෳࡶ͕Ώ͑ʹॊೈ͔ͭݎ࿚ʹႈͳAPIαʔ όʔΛ࡞ΕΔ • ΫϥΠΞϯτ͕Λ࠾൪ͯ͠ઃఆ͢ΔͨΊɺႈͷൣғ͕APIΩϟογϡΑΓݫີ • ಉҰͰͷૢ࡞Λผ͢Δ͜ͱ͕Ͱ͖Δ • ಉҰͰͷϦτϥΠૢ࡞ͱɺ1͔ΒͷΓ͠ͷૢ࡞ผͰ͖Δ • ະॲཧ / ॲཧத / ॲཧࡁΈͱࡉ͔͘ॲཧεςʔλεΛཧͰ͖Δ • ةݥͳߋ৽ܥͷૢ࡞ʹରͯ҆͠શʹႈੑΛ࣋ͨͤΔͨΊʹɺAPIΩϟογϡΑΓ Idempotency-Keyϔομͷํ͕༏Ε͍ͯΔ • ෭࡞༻͕গͳ͍؆қతͳૢ࡞Ͱ͋ΕAPIΩϟογϡͰेͳέʔε 🐟 📱
Slide 35
Slide 35 text
ᶊ ETag ʴ If-Match • ETagʢEntity Tagʣͱ͍͏ߋ৽ରͷόʔδϣϯΛλά ཧ͠ɺIf-MatchϔομͰ͖݅ߋ৽ϦΫΤετΛૹΔ͜ ͱͰ2ॏϦΫΤετΛ͙ํ๏ʢָ؍తϩοΫʣ • αʔόʔଆͰɺΫϥΠΞϯτ͔ΒૹΒΕͨETagͷΛ ൺֱ͠ɺόʔδϣϯ͕Ұகͨ͠ΒॲཧΛߦ͍ɺෆҰகͷ ߹ʹ412 Precondition FailedΛฦ٫͢Δ • ӈͷྫͩͱόʔδϣϯΧϥϜΛETagͱͯ͠ར༻͢Δ͜ͱ Ͱ͖Δ͠ɺ༰ͷtext͔ΒHashΛٻΊͯETagͱ͢Δ͜ ͱՄೳ 🐟 📱
Slide 36
Slide 36 text
ETag ʴ If-Matchͷϑϩʔ 📱ΫϥΠΞϯτ 🐟αʔόʔ ⚙*'7FSTJPO.BUDI ͷϩοΫ &UDʜ σʔλετΞ 🎁ߪೖྃ 1045QBZNFOUT nJUFN@JEJUFN@= )t*G.BUDIu 1BZNFOUJUFN (FU*UFN 7FSTJPO 🐟 📱 (&5JUFNTJUFN@ &5BH 6QEBUF*UFN 7FSTJPO $IFDL $VSSFOU7FSTJPO
Slide 37
Slide 37 text
ETag ʴ If-Matchͷϑϩʔ 📱ΫϥΠΞϯτ 🐟αʔόʔ ⚙*'7FSTJPO/PU.BUDI Τϥʔॲཧ σʔλετΞ 1045QBZNFOUT nJUFN@JEJUFN@= )t*G.BUDIu ❌1SFDPOEJUJPO'BJMFE (FU*UFN 7FSTJPO 🐟 📱 (&5JUFNTJUFN@ &5BH $IFDL $VSSFOU7FSTJPO 💀ߪೖࣦഊ
Slide 38
Slide 38 text
• ָ؍తϩοΫͰ͍Ͱ͍Δํ๏ͳͨΊɺมߋ͞Ε͍͢Ϧιʔεͷಋೖʹෆ͖ • ྫ͑ECαΠτͷߪೖͳͲɺෳਓ͕ಉ࣌ߪೖ͢Δέʔεʹ͍͍ͯͳ͍ • ϢʔβʔͷϓϩϑΟʔϧߋ৽ͳͲɺ1ਓ͔͠ฤू͠ͳ͍έʔεʹ͍͍ͯΔ • ΫϥΠΞϯτ͕ϔομΛ༩͢Δ͜ͱͰ2ॏϦΫΤετͷରࡦΛ͍ͯ͠ΔͰ Idempotency-Keyϔομͱಉ͕ͩ͡ɺతʹҧ͍͕͋Δ • Idempotency-Key : ϔομͷKeyใΛͬͯɺႈͳAPIΛఏڙ͢Δ • ETag ʴ If-Match : ָ؍తϩοΫͰҟͳΔΫϥΠΞϯτؒͰͷಉ࣌ߋ৽Λ͙ ETag ʴ If-Matchͷิ 🐟 📱
Slide 39
Slide 39 text
• 1ͷΈ༻ՄೳͳτʔΫϯΛൃߦ͢Δ͜ͱͰ2ॏϦΫΤετΛ͙Ξϓϩʔν • 2ॏϦΫΤετͷతҎ֎ʹɺਖ਼ͳϦΫΤετͰ͋Δ͜ͱΛอূͯ͠վ͟ΜΛ͍ ͩΓɺ༗ޮظݶΛઃ͚Δ͜ͱͰΑΓηΩϡΞʹ͢ΔͳͲෆਖ਼ରࡦతͰΘΕΔ • τϥϯβΫγϣϯτʔΫϯνΣοΫͱ͍͏ݴ༿Ͱհ͞ΕΔ͜ͱ • CSRFτʔΫϯτʔΫϯΛͬͯϦΫΤετΛνΣοΫ͍ͯ͠ΔͷͰࣅ͍ͯΔ͕ɺ CSRFରࡦͷจ຺ͰτʔΫϯ͕ϫϯλΠϜͰ͋Δ͜ͱඞਢͰͳ͍ ᶋ ϫϯλΠϜτʔΫϯ 🐟 📱
Slide 40
Slide 40 text
ϫϯλΠϜτʔΫϯͷϑϩʔ 📱ΫϥΠΞϯτ 🐟αʔόʔ ⚙*'5PLFOJT7BMJE ͷϩοΫ &UDʜ σʔλετΞ 🎁ߪೖྃ 1045QBZNFOUT nJUFN@JEJUFN@= nUPLFOYZ[ 1BZNFOUJUFN *TTVF UPLFOYZ[ 🐟 📱 1045UPLFOT 5PLFOYZ[ %FMFUF5PLFO $IFDL UPLFOYZ[
Slide 41
Slide 41 text
ϫϯλΠϜτʔΫϯͷϑϩʔ 📱ΫϥΠΞϯτ 🐟αʔόʔ ⚙*'5PLFOJT*OWBMJE Τϥʔॲཧ σʔλετΞ 1045QBZNFOUT nJUFN@JEJUFN@= nUPLFOYZ[ ❌'PSCJEEFO *TTVF UPLFOYZ[ 🐟 📱 1045UPLFOT 5PLFOYZ[ %FMFUF5PLFO $IFDL UPLFOYZ[ 💀ߪೖࣦഊ
Slide 42
Slide 42 text
ޚࡦͷ·ͱΊ
Slide 43
Slide 43 text
ᶃ αϒϛοτϘλϯͷ੍ޚ ᶄ Post-Redirect-Get (PRG) ύλʔϯ ᶅ ഉଞ੍ޚ • Ϧιʔεͷ൵؍ϩοΫ • FIFOʹΑΔॱং੍ޚ • ΞυόΠβϦʔϩοΫ ᶆ ςʔϒϧઃܭ • ঢ়ଶભҠͷϧʔϧԽ • ϢχʔΫ੍ հͨ͠ޚࡦͨͪ ᶇ ϨʔτϦϛοτ ᶈ APIΩϟογϡ ᶉ Idempotency-Keyϔομ ᶊ ETag ʴ If-Match ᶋ ϫϯλΠϜτʔΫϯ
Slide 44
Slide 44 text
αϒϛοτϘλϯͷ੍ޚ ޚࡦͷάϧʔϐϯά Idempotency-Keyϔομ ETag ʴ If-Match ϫϯλΠϜτʔΫϯ ΫϥΠΞϯτͰͷޚࡦ ΫϥΠΞϯτͱόοΫΤϯυͰͷޚࡦ όοΫΤϯυͰͷޚࡦ Post-Redirect-Get (PRG) ύλʔϯ ഉଞ੍ޚ ςʔϒϧઃܭ ϨʔτϦϛοτ APIΩϟογϡ 🐟 📱 🐟 📱
Slide 45
Slide 45 text
ൃදऀͷߟ͑ • جຊαϒϛοτϘλϯͷ੍ޚ / PRGύλʔϯ / ഉଞ੍ޚ + ςʔϒϧઃܭΛߦ ͳ͍ͬͯΕेͳέʔε͕ଟ͍ • σʔλͷ߹ੑ͕֬อ͞ΕΔΑ͏ςʔϒϧઃܭΛ͍ͯ͠Εக໋తͳى͖ͳ͍ • 2ॏϦΫΤετࣗମɺશମͷϦΫΤετ͔ΒݟΔͱΤοδέʔεʹͨΔͷͰɺ2ॏϦ ΫΤετ͕ൃੜͨ͠ࡍͷඃಘΒΕΔϝϦοτΛఆͯ͠ɺదͳΞϓϩʔνΛબ ͖͢ • ϫϯόϯΫͰ࣮ࡍʹར༻͍ͯ͠ΔޚࡦΛཧ༝ͱͱʹհ
Slide 46
Slide 46 text
ϓϦϖΠυΧʔυ / ೖۚ / ग़ۚ Citadel / ֎෦αʔϏεґଘ
Slide 47
Slide 47 text
Idempotency-Keyϔομ • ΫϥΠΞϯτଆͰ࠾൪ͨ͠KeyΛͬͯႈͳAPIΛߏங ͢Δํ๏ • ֎෦αʔϏεͷॏཁͳૢ࡞Λߦ͏ॲཧͰଟ͘ར༻ • ίϯϏχ / ϖΠδʔͳͲͷೖۚใΛൃߦ͢Δॲཧ • ΫϨδοτΧʔυೖۚΛ͢Δࡍͷ3DSೝূॲཧ • ۜߦޱ࠲͔ΒҾ͖མͱ͠ॲཧ
Slide 48
Slide 48 text
Idempotency-Keyϔομ • ֎෦αʔϏεͱͷ࿈ܞॲཧෳࡶʹͳΓ͕ͪ • ෳͷDB τϥϯβΫγϣϯ͕ඞཁͰഉଞ੍ޚ͕ෳࡶʹͳΔ • ࣗαʔϏεଆͱ֎෦αʔϏεଆͷ྆ํͰσʔλෆ߹͕ൃ ੜ͢ΔՄೳੑ͕͋ΓɺϦΧόϦॲཧ͕େม • Idempotency-KeyϔομΛར༻ͯ͠ຊॲཧͷલஈͰ2ॏ ϦΫΤετͷରࡦΛߦ͏͜ͱͰɺσʔλෆ߹͕ൃ ੜ͢ΔϦεΫΛݮΒ͢͜ͱ͕Ͱ͖Δ ֎෦αʔϏε ݺͼग़͠ લॲཧ τϥϯβΫγϣϯ ޙॲཧ τϥϯβΫγϣϯ ֎෦αʔϏεݺͼग़͠ॲཧ Idempotency-Key ϔομʹΑΔޚ
Slide 49
Slide 49 text
Idempotency-Keyϔομ • ࣄނతͳ2ॏϦΫΤετͱҙਤతͳผϦΫΤετΛ۠ผ͢Δ͜ͱ͕Ͱ͖Δͷັྗత • ྫ͑ϓϦϖΠυΧʔυͷೖۚॲཧ࣌ؒͰෳճߦΘΕ͓͔ͯ͘͠ͳ͍ • Key͕ಉ͡ = ࣄނతͳϦΫΤετɺKey͕ҟͳΔ = ҙਤతͳϦΫΤετͱ۠ผͰ͖Δ • ҰํɺKeyͷνΣοΫॲཧొॲཧͳͲͷΦʔόʔϔου͕૿͑ͨΓɺΫϥΠΞϯτଆ ͰͷKey࠾൪ॲཧͷ࣮ͳͲ࣮ίετ͕͔͔ΔͨΊɺಋೖՕॴݶఆత
Slide 50
Slide 50 text
ϫϯλΠϜτʔΫϯ • ΞϓϦͷதͰಛʹॏཁͳॲཧͰ༻ • ύείʔυͷొ / ࠶ઃఆ • Χʔυ൪߸ͷදࣔ • ͋ͱΒ͍νϟʔδۜߦޱ࠲Ҿ͖མͱ͠ͳͲͷೖۚ ॲཧ
Slide 51
Slide 51 text
ϫϯλΠϜτʔΫϯ • Ϣʔβʔͷࣄނతͳ2ॏϦΫΤετΛࢭ͢ΔతͰͳ͘ɺϦΫΤετ༰ͷ౪ௌͳͲ ʹΑΔϦϓϨΠ߈ܸΛ͙తͷͨΊʹ༻ • ϦϓϨΠ߈ܸ : αΠόʔ߈ܸͷҰछͰɺ௨৴ͰҰૹ৴͞Εͨਖ਼نͷσʔλΛड͠ɺͦ ͷ··࠶ૹ৴͢Δ͜ͱͰɺෆਖ਼ͳಈ࡞Λ༠ൃ͢Δ߈ܸ • ೖۚॲཧ͕౪ௌ͞ΕͯԿෆਖ਼ೖۚ͞ΕΔͳͲͷ߈ܸΛ͙ • ࣄނతͳ2ॏϦΫΤετΛ͙ͨΊɺIdempotency-KeyϔομͱΈ߹Θ࣮͍ͤͯͯ͠ ΔAPIଟ͍ • τʔΫϯऔಘϑϩʔͳͲ࣮ίετɺϢʔβʔͷख͕ؒൃੜ͢Δํ๏ͳͷͰɺ࣮Օॴ ηΩϡϦςΟڧΛ্͍͛ͨՕॴͷΈ
Slide 52
Slide 52 text
ϨʔτϦϛοτ • όʔνϟϧΧʔυͱ͍͏ཧతͳΧʔυൃߦ͞ΕͣΧʔυ ൪߸͚ͩೖखͰ͖ΔػೳͷൃߦॲཧͰར༻ • όʔνϟϧΧʔυԿͰ࠶ൃߦͰ͖Δ͕ɺ࣌ؒʹԿ ࠶ൃߦ͢Δ͜ͱਖ਼ৗͳঢ়ଶͰͳ͍ • ؒҧ͑ͯΧʔυൃߦ͕ى͖ͨࡍ֎෦αʔϏεଆͷमਖ਼ඞ ཁͰӡ༻ίετ͕ߴ͍ • Χʔυൃߦ2ͭͷαʔϏεʹލͬͯॲཧ͞ΕΔ͕ɺΧʔυൃ ߦଆͰϩοΫΛऔಘͰ͖ΔదͳϦιʔε͕ଘࡏ͠ͳ͔ͬͨ • ϢʔβʔຖͷൃߦճΛอଘ͠ɺࢦఆճΛ͑ͨΒΤϥʔ ൃੜ͢Δ༷ʹ ϞόΠϧΞϓϦ #'' *TTVJOH"1* $PSF"1* ֎෦αʔϏε
Slide 53
Slide 53 text
ϨʔτϦϛοτ • ഉଞ੍ޚͰ͖ΔΑ͏ʹطଘͷΈΛमਖ਼ͨ͠ΓɺΞυ όΠβϦʔϩοΫݕ౼͕ͨ͠ίεύ؍Ͱෆ࠾༻ • ϨʔτϦϛοτͷ੍ޚςʔϒϧΛҰͭՃ͢ΔఔͰ࣮ݱ Մೳ • Idempotency-Keyϔομͷಋೖݕ౼͕ͨ͠ɺΧʔυൃߦ αʔϏεଆʹͦͷΈ͕͍ͬͯͳ͔ͬͨͨΊෆ࠾༻ • ໓ଟʹൃੜ͠ͳ͍͕ɺ͠ൃੜͨ͠Βσʔλमਖ਼ͷӡ ༻ίετ͕ߴ͍ΛίετͰղܾ https://blog.smartbank.co.jp/entry/2025/03/19/123000
Slide 54
Slide 54 text
ςʔϒϧઃܭ + Ωϟογϡ • ίϯϏχ / ϖΠδʔͳͲͷೖۚํ๏ͰɺϢʔβʔ͕ϨδͰ͓ۚ Λࢧͬͨޙʹྃใ͕WebhookͰૹΒΕΔ • WebhookʹϦτϥΠػೳ͕ఏڙ͞Ε͍ͯΔ͜ͱ͕ଟ͍ • λΠϜΞτ͕ൃੜ͢Δͱ֎෦αʔϏεଆʹΤϥʔผ͞Εͨ ͚Ͳ࣮ࡍʹޭঢ়ଶͱ͍͏σʔλෆ߹͕ൃੜ͢Δ • ϦτϥΠ࣌ʹɺςʔϒϧઃܭͰ߹ੑΛอ͍ͬͯΔ͔ΒͱΤϥʔ ൃੜͤ͞ΔͱΤϥʔϧʔϓ͕ൃੜ͢Δ • ֎෦αʔϏεΛར༻͍ͯ͠Δͱ͖ɺIdempotency-Keyϔομͳ ͲͷΫϥΠΞϯτଆͷมߋ͕Ͱ͖ͳ͍ ֎෦ αʔϏε αʔόʔ POST TIMEOUT RETRY ? DB Table SAVE SUCCESS
Slide 55
Slide 55 text
ςʔϒϧઃܭ + Ωϟογϡ • ςʔϒϧઃܭ্Ұҙ੍ΛೖΕΔͳͲͰ߹ੑΛ֬อ͓ͯ͠ ͖ɺWebhookΛड͚औͬͨࡍʹରϦιʔεͷঢ়ଶΛ֬ೝ ͠ɺॲཧ͍ྃͯͨ͠ΒޭΛฦ͢͜ͱͰႈʹ͢Δ • ͨͩ͠ႈʹ͢ΔϦΫΤετΛಛఆͰ͖ΔIDͳͲؚ͕·Ε͍ͯͳ ͍ͱ࣮ݱͰ͖ͳ͍ͷͰɺ֎෦αʔϏεͷ༷࣍ୈ ֎෦ αʔϏε αʔόʔ POST TIMEOUT RETRY SUCCESS DB Table SAVE FETCH SUCCESS
Slide 56
Slide 56 text
·ͱΊ
Slide 57
Slide 57 text
·ͱΊ • ୭ʹͱͬͯۙͰॏཁͳ2ॏϦΫΤετʹ·ͳ͍͍ͯ͘ੈքΛ࡞Δ • 2ॏϦΫΤετ͕ͲͷΑ͏ͳͳͷ͔આ໌ • 2ॏϦΫΤετͷޚ๏Λ9ݸհ • ϫϯόϯΫͰͷϢʔεέʔεͱ࠾༻͍ͯ͠Δޚ๏Λհ • ۀͰʮͲ͏͠Α͏ʯͱͳͬͨ࣌ʹͥͻݟฦ͍ͯͩ͘͠͞ʂ • ࠓൃදͨ͠ύλʔϯΛ୯ಠ or Έ߹ΘͤΔ͜ͱͰͳΜͱ͔ͳΔέʔε͕ଟ͍ͣ
Slide 58
Slide 58 text
No content