Skip to content

Skip deploy 611#16123

Draft
sahusanket wants to merge 4 commits into
release/6.11from
skip_deploy_611
Draft

Skip deploy 611#16123
sahusanket wants to merge 4 commits into
release/6.11from
skip_deploy_611

Conversation

@sahusanket
Copy link
Copy Markdown
Contributor

No description provided.

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a mechanism to skip application deployment if an identical version and configuration are already present, and enables optimistic locking for Spanner transactions. Feedback focuses on refining the deployment check logic to handle version ranges and version mismatches correctly, using semantic JSON comparison instead of string matching, and adjusting log levels. Additionally, there is a concern regarding the global impact of enabling optimistic locking on Spanner transaction retry rates.

* configuration.
*/
public boolean isAppAlreadyDeployed(ApplicationId appId, AppRequest<?> appRequest) throws Exception {
ApplicationMeta appMeta = store.getLatest(appId.getAppReference());
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The logic currently checks the latest version of the application using appId.getAppReference(). If the appId provided in the request specifies a different version than the latest one currently deployed, the deployment should likely proceed to create that new version, even if the artifact and configuration are identical. Consider verifying that the version in appId matches the version of the existing application found in appMeta.

Comment on lines +765 to +773
try {
io.cdap.cdap.api.artifact.ArtifactVersionRange range = io.cdap.cdap.api.artifact.ArtifactVersionRange
.parse(requestedArtifact.getVersion());
if (!range.versionIsInRange(currentArtifactId.getVersion())) {
return false;
}
} catch (Exception e) {
return false;
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Using ArtifactVersionRange.versionIsInRange to determine if an app is already deployed can be problematic when a version range is requested. If a newer artifact version that also satisfies the range is available in the repository, a standard deployment would typically upgrade the application. By skipping the deployment here, you might prevent such updates. It is safer to skip only if the requested version is a specific version and it matches the currently deployed version exactly.


try {
if (applicationLifecycleService.isAppAlreadyDeployed(appId, appRequest)) {
LOG.warn("Application {} is already deployed",appId );
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The use of LOG.warn is inappropriate here as skipping a deployment because it is already up-to-date is a normal, expected condition. LOG.info or LOG.debug would be more suitable. Additionally, there is a missing space after the comma in the log arguments.

Suggested change
LOG.warn("Application {} is already deployed",appId );
LOG.info("Application {} is already deployed", appId);

* Checks if the application already exists with the exact same artifact and
* configuration.
*/
public boolean isAppAlreadyDeployed(ApplicationId appId, AppRequest<?> appRequest) throws Exception {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The method signature throws Exception, which is too broad. It is better to catch specific exceptions internally or declare more specific exceptions (e.g., IOException) to improve error handling and maintainability.

Comment on lines +780 to +785
String normRequestedConfig = requestedConfigStr == null ? "" : requestedConfigStr.trim();
String normCurrentConfig = currentConfigStr == null ? "" : currentConfigStr.trim();

if (!normRequestedConfig.equals(normCurrentConfig)) {
return false;
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Comparing JSON configurations as trimmed strings is fragile and can lead to false negatives if the JSON key ordering or whitespace differs, even when the configurations are semantically identical. A more robust approach is to compare the configurations as JsonElement objects using GSON's equality check.

public void run(TxRunnable runnable) throws TransactionException {
try {
admin.getDatabaseClient().readWriteTransaction().allowNestedTransaction().run(context -> {
admin.getDatabaseClient().readWriteTransaction(Options.optimisticLock()).allowNestedTransaction().run(context -> {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Enabling Options.optimisticLock() globally for all Spanner transactions is a significant change. While it can improve performance by reducing lock contention during the read phase, it may also increase the rate of transaction aborts and retries in high-contention scenarios. Please ensure this change is intended to be global and has been verified against various CDAP workloads, as it seems unrelated to the 'Skip deploy' logic.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant