|
| 1 | +#include "dst_alterer.h" |
| 2 | +#include "logging.h" |
| 3 | +#include "private_events.h" |
| 4 | + |
| 5 | +#include <ydb/core/base/tablet_pipecache.h> |
| 6 | +#include <ydb/core/tx/schemeshard/schemeshard.h> |
| 7 | +#include <ydb/core/tx/tx_proxy/proxy.h> |
| 8 | +#include <ydb/library/actors/core/actor_bootstrapped.h> |
| 9 | +#include <ydb/library/actors/core/hfunc.h> |
| 10 | + |
| 11 | +namespace NKikimr::NReplication::NController { |
| 12 | + |
| 13 | +using namespace NSchemeShard; |
| 14 | + |
| 15 | +class TDstAlterer: public TActorBootstrapped<TDstAlterer> { |
| 16 | + void AllocateTxId() { |
| 17 | + Send(MakeTxProxyID(), new TEvTxUserProxy::TEvAllocateTxId); |
| 18 | + Become(&TThis::StateAllocateTxId); |
| 19 | + } |
| 20 | + |
| 21 | + STATEFN(StateAllocateTxId) { |
| 22 | + switch (ev->GetTypeRewrite()) { |
| 23 | + hFunc(TEvTxUserProxy::TEvAllocateTxIdResult, Handle); |
| 24 | + default: |
| 25 | + return StateBase(ev); |
| 26 | + } |
| 27 | + } |
| 28 | + |
| 29 | + void Handle(TEvTxUserProxy::TEvAllocateTxIdResult::TPtr& ev) { |
| 30 | + LOG_T("Handle " << ev->Get()->ToString()); |
| 31 | + |
| 32 | + TxId = ev->Get()->TxId; |
| 33 | + PipeCache = ev->Get()->Services.LeaderPipeCache; |
| 34 | + AlterDst(); |
| 35 | + } |
| 36 | + |
| 37 | + void AlterDst() { |
| 38 | + auto ev = MakeHolder<TEvSchemeShard::TEvModifySchemeTransaction>(TxId, SchemeShardId); |
| 39 | + auto& tx = *ev->Record.AddTransaction(); |
| 40 | + tx.SetInternal(true); |
| 41 | + |
| 42 | + switch (Kind) { |
| 43 | + case TReplication::ETargetKind::Table: |
| 44 | + tx.SetOperationType(NKikimrSchemeOp::ESchemeOpAlterTable); |
| 45 | + PathIdFromPathId(DstPathId, tx.MutableAlterTable()->MutablePathId()); |
| 46 | + tx.MutableAlterTable()->MutableReplicationConfig()->SetMode( |
| 47 | + NKikimrSchemeOp::TTableReplicationConfig::REPLICATION_MODE_NONE); |
| 48 | + break; |
| 49 | + } |
| 50 | + |
| 51 | + Send(PipeCache, new TEvPipeCache::TEvForward(ev.Release(), SchemeShardId, true)); |
| 52 | + Become(&TThis::StateAlterDst); |
| 53 | + } |
| 54 | + |
| 55 | + STATEFN(StateAlterDst) { |
| 56 | + switch (ev->GetTypeRewrite()) { |
| 57 | + hFunc(TEvSchemeShard::TEvModifySchemeTransactionResult, Handle); |
| 58 | + hFunc(TEvSchemeShard::TEvNotifyTxCompletionResult, Handle); |
| 59 | + sFunc(TEvents::TEvWakeup, AllocateTxId); |
| 60 | + default: |
| 61 | + return StateBase(ev); |
| 62 | + } |
| 63 | + } |
| 64 | + |
| 65 | + void Handle(TEvSchemeShard::TEvModifySchemeTransactionResult::TPtr& ev) { |
| 66 | + LOG_T("Handle " << ev->Get()->ToString()); |
| 67 | + const auto& record = ev->Get()->Record; |
| 68 | + |
| 69 | + switch (record.GetStatus()) { |
| 70 | + case NKikimrScheme::StatusAccepted: |
| 71 | + Y_DEBUG_ABORT_UNLESS(TxId == record.GetTxId()); |
| 72 | + return SubscribeTx(record.GetTxId()); |
| 73 | + case NKikimrScheme::StatusMultipleModifications: |
| 74 | + return Retry(); |
| 75 | + default: |
| 76 | + return Error(record.GetStatus(), record.GetReason()); |
| 77 | + } |
| 78 | + } |
| 79 | + |
| 80 | + void SubscribeTx(ui64 txId) { |
| 81 | + LOG_D("Subscribe tx" |
| 82 | + << ": txId# " << txId); |
| 83 | + Send(PipeCache, new TEvPipeCache::TEvForward(new TEvSchemeShard::TEvNotifyTxCompletion(txId), SchemeShardId)); |
| 84 | + } |
| 85 | + |
| 86 | + void Handle(TEvSchemeShard::TEvNotifyTxCompletionResult::TPtr& ev) { |
| 87 | + LOG_T("Handle " << ev->Get()->ToString()); |
| 88 | + Success(); |
| 89 | + } |
| 90 | + |
| 91 | + void Handle(TEvPipeCache::TEvDeliveryProblem::TPtr& ev) { |
| 92 | + LOG_T("Handle " << ev->Get()->ToString()); |
| 93 | + |
| 94 | + if (SchemeShardId == ev->Get()->TabletId) { |
| 95 | + return; |
| 96 | + } |
| 97 | + |
| 98 | + Retry(); |
| 99 | + } |
| 100 | + |
| 101 | + void Handle(TEvents::TEvUndelivered::TPtr& ev) { |
| 102 | + LOG_T("Handle " << ev->Get()->ToString()); |
| 103 | + Retry(); |
| 104 | + } |
| 105 | + |
| 106 | + void Success() { |
| 107 | + LOG_I("Success"); |
| 108 | + |
| 109 | + Send(Parent, new TEvPrivate::TEvAlterDstResult(ReplicationId, TargetId)); |
| 110 | + PassAway(); |
| 111 | + } |
| 112 | + |
| 113 | + void Error(NKikimrScheme::EStatus status, const TString& error) { |
| 114 | + LOG_E("Error" |
| 115 | + << ": status# " << status |
| 116 | + << ", reason# " << error); |
| 117 | + |
| 118 | + Send(Parent, new TEvPrivate::TEvAlterDstResult(ReplicationId, TargetId, status, error)); |
| 119 | + PassAway(); |
| 120 | + } |
| 121 | + |
| 122 | + void Retry() { |
| 123 | + LOG_D("Retry"); |
| 124 | + Schedule(RetryInterval, new TEvents::TEvWakeup); |
| 125 | + } |
| 126 | + |
| 127 | +public: |
| 128 | + static constexpr NKikimrServices::TActivity::EType ActorActivityType() { |
| 129 | + return NKikimrServices::TActivity::REPLICATION_CONTROLLER_DST_ALTERER; |
| 130 | + } |
| 131 | + |
| 132 | + explicit TDstAlterer( |
| 133 | + const TActorId& parent, |
| 134 | + ui64 schemeShardId, |
| 135 | + ui64 rid, |
| 136 | + ui64 tid, |
| 137 | + TReplication::ETargetKind kind, |
| 138 | + const TPathId& dstPathId) |
| 139 | + : Parent(parent) |
| 140 | + , SchemeShardId(schemeShardId) |
| 141 | + , ReplicationId(rid) |
| 142 | + , TargetId(tid) |
| 143 | + , Kind(kind) |
| 144 | + , DstPathId(dstPathId) |
| 145 | + , LogPrefix("DstAlterer", ReplicationId, TargetId) |
| 146 | + { |
| 147 | + } |
| 148 | + |
| 149 | + void Bootstrap() { |
| 150 | + if (!DstPathId) { |
| 151 | + Success(); |
| 152 | + } else { |
| 153 | + AllocateTxId(); |
| 154 | + } |
| 155 | + } |
| 156 | + |
| 157 | + STATEFN(StateBase) { |
| 158 | + switch (ev->GetTypeRewrite()) { |
| 159 | + hFunc(TEvPipeCache::TEvDeliveryProblem, Handle); |
| 160 | + hFunc(TEvents::TEvUndelivered, Handle); |
| 161 | + sFunc(TEvents::TEvPoison, PassAway); |
| 162 | + } |
| 163 | + } |
| 164 | + |
| 165 | +private: |
| 166 | + const TActorId Parent; |
| 167 | + const ui64 SchemeShardId; |
| 168 | + const ui64 ReplicationId; |
| 169 | + const ui64 TargetId; |
| 170 | + const TReplication::ETargetKind Kind; |
| 171 | + const TPathId DstPathId; |
| 172 | + const TActorLogPrefix LogPrefix; |
| 173 | + |
| 174 | + ui64 TxId = 0; |
| 175 | + TActorId PipeCache; |
| 176 | + static constexpr auto RetryInterval = TDuration::Seconds(10); |
| 177 | + |
| 178 | +}; // TDstAlterer |
| 179 | + |
| 180 | +IActor* CreateDstAlterer(TReplication::TPtr replication, ui64 targetId, const TActorContext& ctx) { |
| 181 | + const auto* target = replication->FindTarget(targetId); |
| 182 | + Y_ABORT_UNLESS(target); |
| 183 | + return CreateDstAlterer(ctx.SelfID, replication->GetSchemeShardId(), |
| 184 | + replication->GetId(), target->GetId(), target->GetKind(), target->GetDstPathId()); |
| 185 | +} |
| 186 | + |
| 187 | +IActor* CreateDstAlterer(const TActorId& parent, ui64 schemeShardId, |
| 188 | + ui64 rid, ui64 tid, TReplication::ETargetKind kind, const TPathId& dstPathId) |
| 189 | +{ |
| 190 | + return new TDstAlterer(parent, schemeShardId, rid, tid, kind, dstPathId); |
| 191 | +} |
| 192 | + |
| 193 | +} |
0 commit comments