in common/domain/handler.go [374:595]
func (d *handlerImpl) UpdateDomain(
ctx context.Context,
updateRequest *types.UpdateDomainRequest,
) (*types.UpdateDomainResponse, error) {
// must get the metadata (notificationVersion) first
// this version can be regarded as the lock on the v2 domain table
// and since we do not know which table will return the domain afterwards
// this call has to be made
metadata, err := d.domainManager.GetMetadata(ctx)
if err != nil {
return nil, err
}
notificationVersion := metadata.NotificationVersion
getResponse, err := d.domainManager.GetDomain(ctx, &persistence.GetDomainRequest{Name: updateRequest.GetName()})
if err != nil {
return nil, err
}
info := getResponse.Info
config := getResponse.Config
replicationConfig := getResponse.ReplicationConfig
configVersion := getResponse.ConfigVersion
failoverVersion := getResponse.FailoverVersion
failoverNotificationVersion := getResponse.FailoverNotificationVersion
isGlobalDomain := getResponse.IsGlobalDomain
gracefulFailoverEndTime := getResponse.FailoverEndTime
currentActiveCluster := replicationConfig.ActiveClusterName
previousFailoverVersion := getResponse.PreviousFailoverVersion
lastUpdatedTime := time.Unix(0, getResponse.LastUpdatedTime)
// whether history archival config changed
historyArchivalConfigChanged := false
// whether visibility archival config changed
visibilityArchivalConfigChanged := false
// whether active cluster is changed
activeClusterChanged := false
// whether anything other than active cluster is changed
configurationChanged := false
// Update history archival state
historyArchivalState, historyArchivalConfigChanged, err := d.getHistoryArchivalState(
config,
updateRequest,
)
if err != nil {
return nil, err
}
if historyArchivalConfigChanged {
config.HistoryArchivalStatus = historyArchivalState.Status
config.HistoryArchivalURI = historyArchivalState.URI
}
// Update visibility archival state
visibilityArchivalState, visibilityArchivalConfigChanged, err := d.getVisibilityArchivalState(
config,
updateRequest,
)
if err != nil {
return nil, err
}
if visibilityArchivalConfigChanged {
config.VisibilityArchivalStatus = visibilityArchivalState.Status
config.VisibilityArchivalURI = visibilityArchivalState.URI
}
// Update domain info
info, domainInfoChanged := d.updateDomainInfo(
updateRequest,
info,
)
// Update domain config
config, domainConfigChanged, err := d.updateDomainConfiguration(
updateRequest.GetName(),
config,
updateRequest,
)
if err != nil {
return nil, err
}
// Update domain bad binary
config, deleteBinaryChanged, err := d.updateDeleteBadBinary(
config,
updateRequest.DeleteBadBinary,
)
if err != nil {
return nil, err
}
// Update replication config
replicationConfig, replicationConfigChanged, activeClusterChanged, err := d.updateReplicationConfig(
replicationConfig,
updateRequest,
)
if err != nil {
return nil, err
}
// Handle graceful failover request
if updateRequest.FailoverTimeoutInSeconds != nil {
// must update active cluster on a global domain
if !activeClusterChanged || !isGlobalDomain {
return nil, errInvalidGracefulFailover
}
// must start with the passive -> active cluster
if replicationConfig.ActiveClusterName != d.clusterMetadata.GetCurrentClusterName() {
return nil, errCannotDoGracefulFailoverFromCluster
}
if replicationConfig.ActiveClusterName == currentActiveCluster {
return nil, errGracefulFailoverInActiveCluster
}
// cannot have concurrent failover
if gracefulFailoverEndTime != nil {
return nil, errOngoingGracefulFailover
}
endTime := d.timeSource.Now().Add(time.Duration(updateRequest.GetFailoverTimeoutInSeconds()) * time.Second).UnixNano()
gracefulFailoverEndTime = &endTime
previousFailoverVersion = failoverVersion
}
configurationChanged = historyArchivalConfigChanged || visibilityArchivalConfigChanged || domainInfoChanged || domainConfigChanged || deleteBinaryChanged || replicationConfigChanged
if err := d.domainAttrValidator.validateDomainConfig(config); err != nil {
return nil, err
}
if isGlobalDomain {
if err := d.domainAttrValidator.validateDomainReplicationConfigForGlobalDomain(
replicationConfig,
); err != nil {
return nil, err
}
if configurationChanged && activeClusterChanged {
return nil, errCannotDoDomainFailoverAndUpdate
}
if !activeClusterChanged && !d.clusterMetadata.IsPrimaryCluster() {
return nil, errNotPrimaryCluster
}
} else {
if err := d.domainAttrValidator.validateDomainReplicationConfigForLocalDomain(
replicationConfig,
); err != nil {
return nil, err
}
}
if configurationChanged || activeClusterChanged {
now := d.timeSource.Now()
// Check the failover cool down time
if lastUpdatedTime.Add(d.config.FailoverCoolDown(info.Name)).After(now) {
return nil, errDomainUpdateTooFrequent
}
// set the versions
if configurationChanged {
configVersion++
}
if activeClusterChanged && isGlobalDomain {
// Force failover cleans graceful failover state
if updateRequest.FailoverTimeoutInSeconds == nil {
// force failover cleanup graceful failover state
gracefulFailoverEndTime = nil
previousFailoverVersion = common.InitialPreviousFailoverVersion
}
failoverVersion = d.clusterMetadata.GetNextFailoverVersion(
replicationConfig.ActiveClusterName,
failoverVersion,
updateRequest.Name,
)
failoverNotificationVersion = notificationVersion
}
lastUpdatedTime = now
updateReq := createUpdateRequest(
info,
config,
replicationConfig,
configVersion,
failoverVersion,
failoverNotificationVersion,
gracefulFailoverEndTime,
previousFailoverVersion,
lastUpdatedTime,
notificationVersion,
)
err = d.domainManager.UpdateDomain(ctx, &updateReq)
if err != nil {
return nil, err
}
}
if isGlobalDomain {
if err := d.domainReplicator.HandleTransmissionTask(
ctx,
types.DomainOperationUpdate,
info,
config,
replicationConfig,
configVersion,
failoverVersion,
previousFailoverVersion,
isGlobalDomain,
); err != nil {
return nil, err
}
}
response := &types.UpdateDomainResponse{
IsGlobalDomain: isGlobalDomain,
FailoverVersion: failoverVersion,
}
response.DomainInfo, response.Configuration, response.ReplicationConfiguration = d.createResponse(info, config, replicationConfig)
d.logger.Info("Update domain succeeded",
tag.WorkflowDomainName(info.Name),
tag.WorkflowDomainID(info.ID),
)
return response, nil
}