|
10 | 10 | import com.yahoo.config.application.api.DeployLogger; |
11 | 11 | import com.yahoo.config.model.api.ConfigDefinitionRepo; |
12 | 12 | import com.yahoo.config.model.api.EndpointCertificateSecretStore; |
| 13 | +import com.yahoo.config.model.api.Model; |
13 | 14 | import com.yahoo.config.model.api.OnnxModelCost; |
14 | 15 | import com.yahoo.config.model.application.provider.DeployData; |
15 | 16 | import com.yahoo.config.model.application.provider.FilesApplicationPackage; |
|
24 | 25 | import com.yahoo.vespa.config.server.ConfigServerDB; |
25 | 26 | import com.yahoo.vespa.config.server.TimeoutBudget; |
26 | 27 | import com.yahoo.vespa.config.server.application.InheritableApplications; |
| 28 | +import com.yahoo.vespa.config.server.application.Application; |
27 | 29 | import com.yahoo.vespa.config.server.application.ApplicationVersions; |
28 | 30 | import com.yahoo.vespa.config.server.application.TenantApplications; |
29 | 31 | import com.yahoo.vespa.config.server.configchange.ConfigChangeActions; |
30 | 32 | import com.yahoo.vespa.config.server.deploy.TenantFileSystemDirs; |
| 33 | +import com.yahoo.text.Text; |
31 | 34 | import com.yahoo.vespa.config.server.filedistribution.FileDistributionFactory; |
32 | 35 | import com.yahoo.vespa.config.server.http.InvalidApplicationException; |
33 | 36 | import com.yahoo.vespa.config.server.http.UnknownVespaVersionException; |
|
76 | 79 | import java.util.Map; |
77 | 80 | import java.util.Optional; |
78 | 81 | import java.util.Set; |
| 82 | +import java.util.stream.Collectors; |
79 | 83 | import java.util.concurrent.ExecutionException; |
80 | 84 | import java.util.concurrent.Executor; |
81 | 85 | import java.util.concurrent.ExecutorService; |
|
86 | 90 | import java.util.logging.Level; |
87 | 91 | import java.util.logging.Logger; |
88 | 92 |
|
| 93 | +import static com.yahoo.vespa.config.server.session.ActivationTriggers.DeferredReconfiguration; |
89 | 94 | import static com.yahoo.vespa.config.server.session.Session.Status.ACTIVATE; |
90 | 95 | import static com.yahoo.vespa.config.server.session.Session.Status.DEACTIVATE; |
91 | 96 | import static com.yahoo.vespa.config.server.session.Session.Status.NEW; |
@@ -464,18 +469,51 @@ void activate(long sessionId) { |
464 | 469 |
|
465 | 470 | CompletionWaiter waiter = createSessionZooKeeperClient(sessionId).getActiveWaiter(); |
466 | 471 | log.log(Level.FINE, () -> session.logPre() + "Activating " + sessionId); |
467 | | - tenantApplications.activateApplication(ensureApplicationLoaded(session), sessionId); |
| 472 | + |
| 473 | + ApplicationVersions applicationVersions = ensureApplicationLoaded(session); |
| 474 | + applyDeferredReconfigurationOfClusters(session, applicationVersions); |
| 475 | + |
| 476 | + tenantApplications.activateApplication(applicationVersions, sessionId); |
468 | 477 | log.log(Level.FINE, () -> session.logPre() + "Notifying " + waiter); |
469 | 478 | notifyCompletion(waiter); |
470 | 479 | log.log(Level.INFO, session.logPre() + "Session activated: " + sessionId); |
471 | 480 | } |
472 | 481 |
|
| 482 | + /** |
| 483 | + * Marks clusters for deferred reconfiguration in the model, i.e. wait until restart to apply new config. |
| 484 | + * This is similar to {@link com.yahoo.vespa.config.server.deploy.Deployment::applyDeferredReconfigurationOfClusters} |
| 485 | + * but for {@link ActivationTriggers} from {@link RemoteSession} in ZooKeeper |
| 486 | + * rather than from {@link Session} created locally on the config server. |
| 487 | + */ |
| 488 | + private void applyDeferredReconfigurationOfClusters(RemoteSession session, ApplicationVersions applicationVersions) { |
| 489 | + Set<String> clustersWithDeferredReconfiguration = session.getActivationTriggers().deferredReconfigurations().stream() |
| 490 | + .map(DeferredReconfiguration::clusterId) |
| 491 | + .collect(Collectors.toSet()); |
| 492 | + |
| 493 | + if (clustersWithDeferredReconfiguration.isEmpty()) { |
| 494 | + return; |
| 495 | + } |
| 496 | + |
| 497 | + // Get the model and mark clusters for deferred reconfiguration |
| 498 | + Model model = applicationVersions.get(session.getVespaVersion()) |
| 499 | + .map(Application::getModel) |
| 500 | + .orElseThrow(() -> new IllegalStateException( |
| 501 | + "Cannot apply deferred reconfiguration: no model available for session " + session.getSessionId())); |
| 502 | + model.markClustersForDeferredReconfiguration(clustersWithDeferredReconfiguration); |
| 503 | + |
| 504 | + clustersWithDeferredReconfiguration.forEach(clusterName -> |
| 505 | + log.log(Level.INFO, session.logPre() + |
| 506 | + Text.format("Deferring reconfiguration of cluster '%s' until restart is completed", clusterName))); |
| 507 | + } |
| 508 | + |
473 | 509 | private void loadSessionIfActive(RemoteSession session) { |
474 | 510 | for (ApplicationId applicationId : tenantApplications.activeApplications()) { |
475 | 511 | Optional<Long> activeSession = tenantApplications.activeSessionOf(applicationId); |
476 | 512 | if (activeSession.isPresent() && activeSession.get() == session.getSessionId()) { |
477 | 513 | log.log(Level.FINE, () -> "Found active application for session " + session.getSessionId() + " , loading it"); |
478 | | - tenantApplications.activateApplication(ensureApplicationLoaded(session), session.getSessionId()); |
| 514 | + ApplicationVersions applicationVersions = ensureApplicationLoaded(session); |
| 515 | + applyDeferredReconfigurationOfClusters(session, applicationVersions); |
| 516 | + tenantApplications.activateApplication(applicationVersions, session.getSessionId()); |
479 | 517 | log.log(Level.INFO, session.logPre() + "Application activated successfully: " + applicationId + " (generation " + session.getSessionId() + ")"); |
480 | 518 | return; |
481 | 519 | } |
|
0 commit comments