service_outcome_commit.cpp 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. #include "service_outcome_commit.h"
  2. #include "../../../../core/logging/log.h"
  3. #include "../../../../state/activity/bubble_authority/runtime.h"
  4. #include "../../../../state/activity/runtime.h"
  5. #include "../../../../state/matchmaking/matchmaking_state.h"
  6. #include "../../../../state/runtime/runtime.h"
  7. #include "../internal.h"
  8. namespace sunrise::server::bap::encrypted::transactions {
  9. /**
  10. * Commits at most one delayed State transaction.
  11. * @param outcome Checked service result whose pending transaction is used up.
  12. * @param publication Gets connection fields to publish after the output copy.
  13. * @return True when there is no transaction, or the one transaction commits.
  14. */
  15. bool commit(ServiceOutcome& outcome, Publication& publication) noexcept {
  16. publication = {};
  17. if (auto* allocation = transaction_if<state::activity::PendingAllocation>(outcome)) {
  18. const std::uint64_t sessionId = allocation->sessionId;
  19. if (sessionId == state::activity::kAbsentSessionId
  20. || !state::activity::commit(*allocation)) {
  21. return false;
  22. }
  23. publication.activitySessionId = sessionId;
  24. publication.hasActivitySessionBinding = true;
  25. return true;
  26. }
  27. if (auto* plan = transaction_if<activity_message::ActivityPlan>(outcome)) {
  28. if (plan->mutationDomain == activity_message::MutationDomain::entitySlots) {
  29. if (!state::activity::entity_slots::commit(plan->entitySlotMutation)) {
  30. return false;
  31. }
  32. // The keepalive only finds a link that is bound to a session. A link that allocated
  33. // its own session carries the same id, so this rebinds it to itself.
  34. if (plan->delivery == activity_message::Delivery::joinNotifications
  35. && plan->sessionId != state::activity::kAbsentSessionId) {
  36. publication.activitySessionId = plan->sessionId;
  37. publication.hasActivitySessionBinding = true;
  38. publication.activitySessionFromJoin = true;
  39. // The join resets the client's roster container and the grant mirror with it.
  40. // A kept grant leaves that container ungranted, which refuses its placed objects.
  41. state::activity::bubble_authority::clear_grants(plan->sessionId);
  42. }
  43. return true;
  44. }
  45. if (plan->mutationDomain == activity_message::MutationDomain::membership) {
  46. return state::activity::membership::commit(plan->membershipMutation);
  47. }
  48. // The retained patch epoch is connection state, so it commits nothing here.
  49. return plan->mutationDomain == activity_message::MutationDomain::patchEpoch;
  50. }
  51. if (auto* mutation = transaction_if<state::matchmaking::PendingMutation>(outcome)) {
  52. return state::matchmaking::commit(*mutation);
  53. }
  54. if (auto* transaction = transaction_if<EquipmentSwapTransaction>(outcome)) {
  55. const bool committed = state::commit_equipment_swap(transaction->pending);
  56. core::log::write(core::log::Channel::server,
  57. committed ? core::log::Level::debug : core::log::Level::warn,
  58. committed ? "ev=equip stage=transaction_commit result=ok"
  59. : "ev=equip stage=transaction_commit result=fail");
  60. return committed;
  61. }
  62. if (auto* transaction = transaction_if<SubclassSelectionTransaction>(outcome)) {
  63. const bool committed = state::commit_subclass_selection(transaction->pending);
  64. core::log::write(core::log::Channel::server,
  65. committed ? core::log::Level::debug : core::log::Level::warn,
  66. committed ? "ev=subclass_select stage=transaction_commit result=ok"
  67. : "ev=subclass_select stage=transaction_commit result=fail");
  68. if (committed) {
  69. // The published ability buckets are keyed off the selection that just changed; wake
  70. // the investment worker so its next pump rebuilds them instead of waiting on whatever
  71. // cadence would otherwise trigger a fresh slice.
  72. client::content::investment::worker::request_slice();
  73. }
  74. return committed;
  75. }
  76. if (auto* transaction = transaction_if<ItemAcquisitionTransaction>(outcome)) {
  77. const bool committed = state::commit_item_acquisition(transaction->pending);
  78. core::log::write(core::log::Channel::server,
  79. committed ? core::log::Level::debug : core::log::Level::warn,
  80. committed ? "ev=acquire stage=transaction_commit result=ok"
  81. : "ev=acquire stage=transaction_commit result=fail");
  82. return committed;
  83. }
  84. if (auto* transaction = transaction_if<SocketPlugTransaction>(outcome)) {
  85. const bool committed = state::commit_socket_plug(transaction->pending);
  86. core::log::write(core::log::Channel::server,
  87. committed ? core::log::Level::debug : core::log::Level::warn,
  88. committed ? "ev=socket_plug stage=transaction_commit result=ok"
  89. : "ev=socket_plug stage=transaction_commit result=fail");
  90. return committed;
  91. }
  92. if (auto* transaction = transaction_if<ItemStateTransaction>(outcome)) {
  93. const bool committed = state::commit_item_state(transaction->pending);
  94. core::log::write(core::log::Channel::server,
  95. committed ? core::log::Level::debug : core::log::Level::warn,
  96. committed ? "ev=item_state stage=transaction_commit result=ok"
  97. : "ev=item_state stage=transaction_commit result=fail");
  98. return committed;
  99. }
  100. if (auto* transaction = transaction_if<ProfileItemAcquisitionTransaction>(outcome)) {
  101. const bool committed = state::commit_profile_item_acquisition(transaction->pending);
  102. core::log::write(core::log::Channel::server,
  103. committed ? core::log::Level::debug : core::log::Level::warn,
  104. committed ? "ev=profile_acquire stage=transaction_commit result=ok"
  105. : "ev=profile_acquire stage=transaction_commit result=fail");
  106. return committed;
  107. }
  108. if (auto* transaction = transaction_if<ItemDismantleTransaction>(outcome)) {
  109. const bool committed = state::commit_item_dismantle(transaction->pending);
  110. core::log::write(core::log::Channel::server,
  111. committed ? core::log::Level::debug : core::log::Level::warn,
  112. committed ? "ev=dismantle stage=transaction_commit result=ok"
  113. : "ev=dismantle stage=transaction_commit result=fail");
  114. return committed;
  115. }
  116. return true;
  117. }
  118. } // namespace sunrise::server::bap::encrypted::transactions