diff --git a/.codegen/_openapi_sha b/.codegen/_openapi_sha index 690bae93e..44bb39b3e 100644 --- a/.codegen/_openapi_sha +++ b/.codegen/_openapi_sha @@ -1 +1 @@ -e6695b39732dc7caa2f6c2032053651b980a2123 \ No newline at end of file +ffabf6f202eacded36c296686ff6b41e6e2bddee \ No newline at end of file diff --git a/.gitattributes b/.gitattributes index b3d5dc5c7..d8e5a5db0 100644 --- a/.gitattributes +++ b/.gitattributes @@ -2446,6 +2446,13 @@ databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/PublishSpec.java databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/PublishSpecPublishMode.java linguist-generated=true databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/PublishTableRequest.java linguist-generated=true databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/PublishTableResponse.java linguist-generated=true +databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/PurgeFeatureEntitiesMetadata.java linguist-generated=true +databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/PurgeFeatureEntitiesMetadataState.java linguist-generated=true +databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/PurgeFeatureEntitiesOperation.java linguist-generated=true +databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/PurgeFeatureEntitiesRequest.java linguist-generated=true +databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/PurgeFeatureEntitiesResponse.java linguist-generated=true +databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/PurgeFeatureEntitiesResult.java linguist-generated=true +databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/PurgeFeatureEntitiesResultState.java linguist-generated=true databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/RegisteredModelAccessControlRequest.java linguist-generated=true databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/RegisteredModelAccessControlResponse.java linguist-generated=true databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/RegisteredModelPermission.java linguist-generated=true diff --git a/NEXT_CHANGELOG.md b/NEXT_CHANGELOG.md index 9830931de..e5df20fa0 100644 --- a/NEXT_CHANGELOG.md +++ b/NEXT_CHANGELOG.md @@ -15,3 +15,6 @@ ### Internal Changes ### API Changes +* Add `purgeFeatureEntities()` method for `workspaceClient.featureEngineering()` service. +* Add `budgetPolicyId` and `tags` fields for `com.databricks.sdk.service.ml.IngestionConfig`. +* Add `budgetPolicyId` and `tags` fields for `com.databricks.sdk.service.ml.MaterializedFeature`. \ No newline at end of file diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/cleanrooms/CleanRoomAsset.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/cleanrooms/CleanRoomAsset.java index c855faf86..c1e0073fb 100644 --- a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/cleanrooms/CleanRoomAsset.java +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/cleanrooms/CleanRoomAsset.java @@ -54,7 +54,8 @@ public class CleanRoomAsset { * *shared_catalog*.*shared_schema*.*asset_name* * *

For notebooks, the name is the notebook file name. For jar analyses, the name is the jar - * analysis name. + * analysis name. For Genie spaces, the name is derived from the clean room; the caller does not + * choose it. */ @JsonProperty("name") private String name; diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/cleanrooms/UpdateCleanRoomAssetRequest.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/cleanrooms/UpdateCleanRoomAssetRequest.java index 57d530c52..ad85ebb9f 100644 --- a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/cleanrooms/UpdateCleanRoomAssetRequest.java +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/cleanrooms/UpdateCleanRoomAssetRequest.java @@ -31,7 +31,8 @@ public class UpdateCleanRoomAssetRequest { * *shared_catalog*.*shared_schema*.*asset_name* * *

For notebooks, the name is the notebook file name. For jar analyses, the name is the jar - * analysis name. + * analysis name. For Genie spaces, the name is derived from the clean room; the caller does not + * choose it. */ @JsonIgnore private String name; diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/FeatureEngineeringAPI.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/FeatureEngineeringAPI.java index b46490323..9dc6bbbe0 100644 --- a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/FeatureEngineeringAPI.java +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/FeatureEngineeringAPI.java @@ -222,6 +222,12 @@ public Iterable listStreams(ListStreamsRequest request) { }); } + /** Purge materialized feature values for specified entities. */ + public PurgeFeatureEntitiesOperation purgeFeatureEntities(PurgeFeatureEntitiesRequest request) { + Operation operation = impl.purgeFeatureEntities(request); + return new PurgeFeatureEntitiesOperation(impl, operation); + } + /** Update a Feature. */ public Feature updateFeature(UpdateFeatureRequest request) { return impl.updateFeature(request); diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/FeatureEngineeringImpl.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/FeatureEngineeringImpl.java index ac04b09e9..6cc228e38 100644 --- a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/FeatureEngineeringImpl.java +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/FeatureEngineeringImpl.java @@ -378,6 +378,27 @@ public ListStreamsResponse listStreams(ListStreamsRequest request) { } } + @Override + public Operation purgeFeatureEntities(PurgeFeatureEntitiesRequest request) { + String path = "/api/2.0/feature-engineering/features:purgeFeatureEntities"; + try { + Request req = new Request("POST", path, apiClient.serialize(request)); + + if (request.getRequestId() == null || request.getRequestId().isEmpty()) { + request.setRequestId(UUID.randomUUID().toString()); + } + ApiClient.setQuery(req, request); + req.withHeader("Accept", "application/json"); + req.withHeader("Content-Type", "application/json"); + if (apiClient.workspaceId() != null) { + req.withHeader("X-Databricks-Workspace-Id", apiClient.workspaceId()); + } + return apiClient.execute(req, Operation.class); + } catch (IOException e) { + throw new DatabricksException("IO error: " + e.getMessage(), e); + } + } + @Override public Feature updateFeature(UpdateFeatureRequest request) { String path = String.format("/api/2.0/feature-engineering/features/%s", request.getFullName()); diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/FeatureEngineeringService.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/FeatureEngineeringService.java index 132ee12c5..edadfa9cf 100644 --- a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/FeatureEngineeringService.java +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/FeatureEngineeringService.java @@ -88,6 +88,9 @@ ListMaterializedFeaturesResponse listMaterializedFeatures( /** List Streams under a given catalog.schema parent. */ ListStreamsResponse listStreams(ListStreamsRequest listStreamsRequest); + /** Purge materialized feature values for specified entities. */ + Operation purgeFeatureEntities(PurgeFeatureEntitiesRequest purgeFeatureEntitiesRequest); + /** Update a Feature. */ Feature updateFeature(UpdateFeatureRequest updateFeatureRequest); diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/IngestionConfig.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/IngestionConfig.java index 0bea31b14..3575539de 100644 --- a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/IngestionConfig.java +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/IngestionConfig.java @@ -6,6 +6,7 @@ import com.databricks.sdk.support.ToStringer; import com.fasterxml.jackson.annotation.JsonProperty; import java.util.Collection; +import java.util.Map; import java.util.Objects; /** @@ -31,6 +32,13 @@ public class IngestionConfig { @JsonProperty("backfill_source") private BackfillSource backfillSource; + /** + * The ID of the budget policy used to attribute the serverless compute cost of this stream's + * managed ingestion. If not specified, a default budget policy may be applied. + */ + @JsonProperty("budget_policy_id") + private String budgetPolicyId; + /** * Column paths used to identify duplicate rows during ingestion; only one row per distinct * combination of these values is kept. Use dot notation for nested fields (e.g. `value.user_id`). @@ -59,6 +67,17 @@ public class IngestionConfig { @JsonProperty("ingestion_pipeline_id") private String ingestionPipelineId; + /** + * Custom tags to associate with this stream's managed ingestion. They are applied to the + * ingestion pipeline and its forward-fill and backfill jobs, and forwarded to the underlying + * compute as cluster tags, so ingestion cost can be attributed in the billing system tables. + * These tags apply only to the managed ingestion compute; they are not applied to the Stream + * entity itself, and are distinct from any Unity Catalog tags on the Stream. A maximum of 25 tags + * is supported; keys and values are subject to the same limitations as cluster tags. + */ + @JsonProperty("tags") + private Map tags; + public IngestionConfig setBackfillJobId(Long backfillJobId) { this.backfillJobId = backfillJobId; return this; @@ -77,6 +96,15 @@ public BackfillSource getBackfillSource() { return backfillSource; } + public IngestionConfig setBudgetPolicyId(String budgetPolicyId) { + this.budgetPolicyId = budgetPolicyId; + return this; + } + + public String getBudgetPolicyId() { + return budgetPolicyId; + } + public IngestionConfig setDeduplicationColumns(Collection deduplicationColumns) { this.deduplicationColumns = deduplicationColumns; return this; @@ -113,6 +141,15 @@ public String getIngestionPipelineId() { return ingestionPipelineId; } + public IngestionConfig setTags(Map tags) { + this.tags = tags; + return this; + } + + public Map getTags() { + return tags; + } + @Override public boolean equals(Object o) { if (this == o) return true; @@ -120,10 +157,12 @@ public boolean equals(Object o) { IngestionConfig that = (IngestionConfig) o; return Objects.equals(backfillJobId, that.backfillJobId) && Objects.equals(backfillSource, that.backfillSource) + && Objects.equals(budgetPolicyId, that.budgetPolicyId) && Objects.equals(deduplicationColumns, that.deduplicationColumns) && Objects.equals(ingestionDestination, that.ingestionDestination) && Objects.equals(ingestionJobId, that.ingestionJobId) - && Objects.equals(ingestionPipelineId, that.ingestionPipelineId); + && Objects.equals(ingestionPipelineId, that.ingestionPipelineId) + && Objects.equals(tags, that.tags); } @Override @@ -131,10 +170,12 @@ public int hashCode() { return Objects.hash( backfillJobId, backfillSource, + budgetPolicyId, deduplicationColumns, ingestionDestination, ingestionJobId, - ingestionPipelineId); + ingestionPipelineId, + tags); } @Override @@ -142,10 +183,12 @@ public String toString() { return new ToStringer(IngestionConfig.class) .add("backfillJobId", backfillJobId) .add("backfillSource", backfillSource) + .add("budgetPolicyId", budgetPolicyId) .add("deduplicationColumns", deduplicationColumns) .add("ingestionDestination", ingestionDestination) .add("ingestionJobId", ingestionJobId) .add("ingestionPipelineId", ingestionPipelineId) + .add("tags", tags) .toString(); } } diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/MaterializedFeature.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/MaterializedFeature.java index 1cce14b03..1601311e5 100644 --- a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/MaterializedFeature.java +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/MaterializedFeature.java @@ -5,11 +5,19 @@ import com.databricks.sdk.support.Generated; import com.databricks.sdk.support.ToStringer; import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.Map; import java.util.Objects; /** A materialized feature represents a feature that is continuously computed and stored. */ @Generated public class MaterializedFeature { + /** + * The ID of the budget policy used to attribute the serverless compute cost of this + * materialization. If not specified, a default budget policy may be applied. + */ + @JsonProperty("budget_policy_id") + private String budgetPolicyId; + /** */ @JsonProperty("cron_schedule") private String cronSchedule; @@ -80,6 +88,27 @@ public class MaterializedFeature { @JsonProperty("table_trigger") private TableTrigger tableTrigger; + /** + * Custom tags to associate with this materialization. They are applied to the materialization job + * (for batch features) or pipeline (for streaming features) and forwarded to the underlying + * compute as cluster tags, so materialization cost can be attributed in the billing system + * tables. These tags apply only to the materialization compute; they are not applied to the Unity + * Catalog Feature resource itself, whose tags are managed separately through the Unity Catalog + * tagging API. A maximum of 25 tags is supported; keys and values are subject to the same + * limitations as cluster tags. + */ + @JsonProperty("tags") + private Map tags; + + public MaterializedFeature setBudgetPolicyId(String budgetPolicyId) { + this.budgetPolicyId = budgetPolicyId; + return this; + } + + public String getBudgetPolicyId() { + return budgetPolicyId; + } + public MaterializedFeature setCronSchedule(String cronSchedule) { this.cronSchedule = cronSchedule; return this; @@ -198,12 +227,22 @@ public TableTrigger getTableTrigger() { return tableTrigger; } + public MaterializedFeature setTags(Map tags) { + this.tags = tags; + return this; + } + + public Map getTags() { + return tags; + } + @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; MaterializedFeature that = (MaterializedFeature) o; - return Objects.equals(cronSchedule, that.cronSchedule) + return Objects.equals(budgetPolicyId, that.budgetPolicyId) + && Objects.equals(cronSchedule, that.cronSchedule) && Objects.equals(cronScheduleTrigger, that.cronScheduleTrigger) && Objects.equals(featureName, that.featureName) && Objects.equals(isOnline, that.isOnline) @@ -215,12 +254,14 @@ public boolean equals(Object o) { && Objects.equals(pipelineScheduleState, that.pipelineScheduleState) && Objects.equals(streamingMode, that.streamingMode) && Objects.equals(tableName, that.tableName) - && Objects.equals(tableTrigger, that.tableTrigger); + && Objects.equals(tableTrigger, that.tableTrigger) + && Objects.equals(tags, that.tags); } @Override public int hashCode() { return Objects.hash( + budgetPolicyId, cronSchedule, cronScheduleTrigger, featureName, @@ -233,12 +274,14 @@ public int hashCode() { pipelineScheduleState, streamingMode, tableName, - tableTrigger); + tableTrigger, + tags); } @Override public String toString() { return new ToStringer(MaterializedFeature.class) + .add("budgetPolicyId", budgetPolicyId) .add("cronSchedule", cronSchedule) .add("cronScheduleTrigger", cronScheduleTrigger) .add("featureName", featureName) @@ -252,6 +295,7 @@ public String toString() { .add("streamingMode", streamingMode) .add("tableName", tableName) .add("tableTrigger", tableTrigger) + .add("tags", tags) .toString(); } } diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/PurgeFeatureEntitiesMetadata.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/PurgeFeatureEntitiesMetadata.java new file mode 100644 index 000000000..d92822847 --- /dev/null +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/PurgeFeatureEntitiesMetadata.java @@ -0,0 +1,122 @@ +// Code generated from OpenAPI specs by Databricks SDK Generator. DO NOT EDIT. + +package com.databricks.sdk.service.ml; + +import com.databricks.sdk.support.Generated; +import com.databricks.sdk.support.ToStringer; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.google.protobuf.Timestamp; +import java.util.Collection; +import java.util.Objects; + +/** Progress and configuration for a feature entity purge. */ +@Generated +public class PurgeFeatureEntitiesMetadata { + /** Time at which the purge operation was created. */ + @JsonProperty("create_time") + private Timestamp createTime; + + /** Fully qualified name of the Unity Catalog Delta table containing the entity keys to purge. */ + @JsonProperty("entities_table") + private String entitiesTable; + + /** Version of the entities table used by the purge. */ + @JsonProperty("entities_table_version") + private String entitiesTableVersion; + + /** Fully qualified names of the features targeted by the purge. */ + @JsonProperty("features") + private Collection features; + + /** ID of the job that executes this purge. */ + @JsonProperty("job_id") + private Long jobId; + + /** Current state of the purge operation. */ + @JsonProperty("state") + private PurgeFeatureEntitiesMetadataState state; + + public PurgeFeatureEntitiesMetadata setCreateTime(Timestamp createTime) { + this.createTime = createTime; + return this; + } + + public Timestamp getCreateTime() { + return createTime; + } + + public PurgeFeatureEntitiesMetadata setEntitiesTable(String entitiesTable) { + this.entitiesTable = entitiesTable; + return this; + } + + public String getEntitiesTable() { + return entitiesTable; + } + + public PurgeFeatureEntitiesMetadata setEntitiesTableVersion(String entitiesTableVersion) { + this.entitiesTableVersion = entitiesTableVersion; + return this; + } + + public String getEntitiesTableVersion() { + return entitiesTableVersion; + } + + public PurgeFeatureEntitiesMetadata setFeatures(Collection features) { + this.features = features; + return this; + } + + public Collection getFeatures() { + return features; + } + + public PurgeFeatureEntitiesMetadata setJobId(Long jobId) { + this.jobId = jobId; + return this; + } + + public Long getJobId() { + return jobId; + } + + public PurgeFeatureEntitiesMetadata setState(PurgeFeatureEntitiesMetadataState state) { + this.state = state; + return this; + } + + public PurgeFeatureEntitiesMetadataState getState() { + return state; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + PurgeFeatureEntitiesMetadata that = (PurgeFeatureEntitiesMetadata) o; + return Objects.equals(createTime, that.createTime) + && Objects.equals(entitiesTable, that.entitiesTable) + && Objects.equals(entitiesTableVersion, that.entitiesTableVersion) + && Objects.equals(features, that.features) + && Objects.equals(jobId, that.jobId) + && Objects.equals(state, that.state); + } + + @Override + public int hashCode() { + return Objects.hash(createTime, entitiesTable, entitiesTableVersion, features, jobId, state); + } + + @Override + public String toString() { + return new ToStringer(PurgeFeatureEntitiesMetadata.class) + .add("createTime", createTime) + .add("entitiesTable", entitiesTable) + .add("entitiesTableVersion", entitiesTableVersion) + .add("features", features) + .add("jobId", jobId) + .add("state", state) + .toString(); + } +} diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/PurgeFeatureEntitiesMetadataState.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/PurgeFeatureEntitiesMetadataState.java new file mode 100644 index 000000000..b109cac39 --- /dev/null +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/PurgeFeatureEntitiesMetadataState.java @@ -0,0 +1,15 @@ +// Code generated from OpenAPI specs by Databricks SDK Generator. DO NOT EDIT. + +package com.databricks.sdk.service.ml; + +import com.databricks.sdk.support.Generated; + +/** Lifecycle state of a feature entity purge. */ +@Generated +public enum PurgeFeatureEntitiesMetadataState { + CANCELLED, + FAILED, + PENDING, + RUNNING, + SUCCEEDED, +} diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/PurgeFeatureEntitiesOperation.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/PurgeFeatureEntitiesOperation.java new file mode 100644 index 000000000..dcf37b16e --- /dev/null +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/PurgeFeatureEntitiesOperation.java @@ -0,0 +1,163 @@ +// Code generated from OpenAPI specs by Databricks SDK Generator. DO NOT EDIT. +package com.databricks.sdk.service.ml; + +import com.databricks.sdk.core.DatabricksException; +import com.databricks.sdk.core.logging.Logger; +import com.databricks.sdk.core.logging.LoggerFactory; +import com.databricks.sdk.core.utils.SerDeUtils; +import com.databricks.sdk.service.common.lro.LroOptions; +import com.databricks.sdk.support.Generated; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.time.Duration; +import java.util.Optional; +import java.util.concurrent.TimeoutException; + +/** + * Wrapper for interacting with a long-running purgeFeatureEntities operation. Provides methods to + * wait for completion, check status, cancel, and access metadata. + */ +@Generated +public class PurgeFeatureEntitiesOperation { + private static final Logger LOG = LoggerFactory.getLogger(PurgeFeatureEntitiesOperation.class); + + private final FeatureEngineeringService impl; + private Operation operation; + private final ObjectMapper objectMapper; + + public PurgeFeatureEntitiesOperation(FeatureEngineeringService impl, Operation operation) { + this.impl = impl; + this.operation = operation; + this.objectMapper = SerDeUtils.createMapper(); + } + + /** + * Wait for the operation to complete and return the resulting PurgeFeatureEntitiesResponse. Waits + * indefinitely if no timeout is specified. + * + * @return the created PurgeFeatureEntitiesResponse + * @throws TimeoutException if the operation doesn't complete within the timeout + * @throws DatabricksException if the operation fails + */ + public PurgeFeatureEntitiesResponse waitForCompletion() throws TimeoutException { + return waitForCompletion(Optional.empty()); + } + + /** + * Wait for the operation to complete and return the resulting PurgeFeatureEntitiesResponse. + * + * @param options the options for configuring the wait behavior, can be empty for defaults + * @return the created PurgeFeatureEntitiesResponse + * @throws TimeoutException if the operation doesn't complete within the timeout + * @throws DatabricksException if the operation fails + */ + public PurgeFeatureEntitiesResponse waitForCompletion(Optional options) + throws TimeoutException { + Optional timeout = options.flatMap(LroOptions::getTimeout); + long deadline = + timeout.isPresent() + ? System.currentTimeMillis() + timeout.get().toMillis() + : Long.MAX_VALUE; + String statusMessage = "polling operation..."; + int attempt = 1; + + while (System.currentTimeMillis() < deadline) { + // Refresh the operation state + refreshOperation(); + + if (operation.getDone() != null && operation.getDone()) { + // Operation completed, check for success or failure + if (operation.getError() != null) { + String errorMsg = "unknown error"; + if (operation.getError().getMessage() != null + && !operation.getError().getMessage().isEmpty()) { + errorMsg = operation.getError().getMessage(); + } + + if (operation.getError().getErrorCode() != null) { + errorMsg = String.format("[%s] %s", operation.getError().getErrorCode(), errorMsg); + } + + throw new DatabricksException("Operation failed: " + errorMsg); + } + + // Operation completed successfully, unmarshal response + if (operation.getResponse() == null) { + throw new DatabricksException("Operation completed but no response available"); + } + + try { + JsonNode responseJson = objectMapper.valueToTree(operation.getResponse()); + return objectMapper.treeToValue(responseJson, PurgeFeatureEntitiesResponse.class); + } catch (JsonProcessingException e) { + throw new DatabricksException( + "Failed to unmarshal purgeFeatureEntitiesResponse response: " + e.getMessage(), e); + } + } + + // Operation still in progress, wait before polling again + String prefix = String.format("operation=%s", operation.getName()); + int sleep = Math.min(attempt, 10); // sleep 10s max per attempt + LOG.info("{}: operation in progress (sleeping ~{}s)", prefix, sleep); + + try { + Thread.sleep((long) (sleep * 1000L + Math.random() * 1000)); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new DatabricksException("Current thread was interrupted", e); + } + attempt++; + } + + String timeoutMessage = + timeout.isPresent() + ? String.format("Operation timed out after %s: %s", timeout.get(), statusMessage) + : String.format("Operation timed out: %s", statusMessage); + throw new TimeoutException(timeoutMessage); + } + + /** + * Get the operation name. + * + * @return the operation name + */ + public String getName() { + return operation.getName(); + } + + /** + * Get the operation metadata. + * + * @return the operation metadata, or null if not available + * @throws DatabricksException if the metadata cannot be deserialized + */ + public PurgeFeatureEntitiesMetadata getMetadata() { + if (operation.getMetadata() == null) { + return null; + } + + try { + JsonNode metadataJson = objectMapper.valueToTree(operation.getMetadata()); + return objectMapper.treeToValue(metadataJson, PurgeFeatureEntitiesMetadata.class); + } catch (JsonProcessingException e) { + throw new DatabricksException("Failed to unmarshal operation metadata: " + e.getMessage(), e); + } + } + + /** + * Check if the operation is done. This method refreshes the operation state before checking. + * + * @return true if the operation is complete, false otherwise + * @throws DatabricksException if the status check fails + */ + public boolean isDone() { + refreshOperation(); + return operation.getDone() != null && operation.getDone(); + } + + /** Refresh the operation state by polling the server. */ + private void refreshOperation() { + operation = impl.getOperation(new GetOperationRequest().setName(operation.getName())); + } +} diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/PurgeFeatureEntitiesRequest.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/PurgeFeatureEntitiesRequest.java new file mode 100644 index 000000000..d31fc7668 --- /dev/null +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/PurgeFeatureEntitiesRequest.java @@ -0,0 +1,87 @@ +// Code generated from OpenAPI specs by Databricks SDK Generator. DO NOT EDIT. + +package com.databricks.sdk.service.ml; + +import com.databricks.sdk.support.Generated; +import com.databricks.sdk.support.ToStringer; +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.Collection; +import java.util.Objects; + +/** + * Request to purge materialized feature values for entities listed in a Unity Catalog Delta table. + */ +@Generated +public class PurgeFeatureEntitiesRequest { + /** + * Fully qualified name of the Unity Catalog Delta table containing the entity keys to purge. The + * table may contain a subset of each feature's entity-key columns. A partial key match deletes + * all feature rows matching the provided key values. Non-key columns are rejected; null key + * values are allowed. + */ + @JsonProperty("entities_table") + private String entitiesTable; + + /** + * Fully qualified names of the features to purge. At least one nonempty feature name is required. + * A request may contain at most 10000 features; submit additional features in separate requests. + * Duplicate features are rejected. + */ + @JsonProperty("features") + private Collection features; + + /** Optional UUID4 idempotency token for the request. */ + @JsonProperty("request_id") + private String requestId; + + public PurgeFeatureEntitiesRequest setEntitiesTable(String entitiesTable) { + this.entitiesTable = entitiesTable; + return this; + } + + public String getEntitiesTable() { + return entitiesTable; + } + + public PurgeFeatureEntitiesRequest setFeatures(Collection features) { + this.features = features; + return this; + } + + public Collection getFeatures() { + return features; + } + + public PurgeFeatureEntitiesRequest setRequestId(String requestId) { + this.requestId = requestId; + return this; + } + + public String getRequestId() { + return requestId; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + PurgeFeatureEntitiesRequest that = (PurgeFeatureEntitiesRequest) o; + return Objects.equals(entitiesTable, that.entitiesTable) + && Objects.equals(features, that.features) + && Objects.equals(requestId, that.requestId); + } + + @Override + public int hashCode() { + return Objects.hash(entitiesTable, features, requestId); + } + + @Override + public String toString() { + return new ToStringer(PurgeFeatureEntitiesRequest.class) + .add("entitiesTable", entitiesTable) + .add("features", features) + .add("requestId", requestId) + .toString(); + } +} diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/PurgeFeatureEntitiesResponse.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/PurgeFeatureEntitiesResponse.java new file mode 100644 index 000000000..23bd0614c --- /dev/null +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/PurgeFeatureEntitiesResponse.java @@ -0,0 +1,76 @@ +// Code generated from OpenAPI specs by Databricks SDK Generator. DO NOT EDIT. + +package com.databricks.sdk.service.ml; + +import com.databricks.sdk.support.Generated; +import com.databricks.sdk.support.ToStringer; +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.Collection; +import java.util.Objects; + +/** Result of a completed feature entity purge. */ +@Generated +public class PurgeFeatureEntitiesResponse { + /** Metadata about the purge operation. */ + @JsonProperty("metadata") + private PurgeFeatureEntitiesMetadata metadata; + + /** Per-feature purge results. */ + @JsonProperty("results") + private Collection results; + + /** State of the purge operation. */ + @JsonProperty("state") + private PurgeFeatureEntitiesMetadataState state; + + public PurgeFeatureEntitiesResponse setMetadata(PurgeFeatureEntitiesMetadata metadata) { + this.metadata = metadata; + return this; + } + + public PurgeFeatureEntitiesMetadata getMetadata() { + return metadata; + } + + public PurgeFeatureEntitiesResponse setResults(Collection results) { + this.results = results; + return this; + } + + public Collection getResults() { + return results; + } + + public PurgeFeatureEntitiesResponse setState(PurgeFeatureEntitiesMetadataState state) { + this.state = state; + return this; + } + + public PurgeFeatureEntitiesMetadataState getState() { + return state; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + PurgeFeatureEntitiesResponse that = (PurgeFeatureEntitiesResponse) o; + return Objects.equals(metadata, that.metadata) + && Objects.equals(results, that.results) + && Objects.equals(state, that.state); + } + + @Override + public int hashCode() { + return Objects.hash(metadata, results, state); + } + + @Override + public String toString() { + return new ToStringer(PurgeFeatureEntitiesResponse.class) + .add("metadata", metadata) + .add("results", results) + .add("state", state) + .toString(); + } +} diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/PurgeFeatureEntitiesResult.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/PurgeFeatureEntitiesResult.java new file mode 100644 index 000000000..640668106 --- /dev/null +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/PurgeFeatureEntitiesResult.java @@ -0,0 +1,90 @@ +// Code generated from OpenAPI specs by Databricks SDK Generator. DO NOT EDIT. + +package com.databricks.sdk.service.ml; + +import com.databricks.sdk.support.Generated; +import com.databricks.sdk.support.ToStringer; +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.Objects; + +/** Result of purging one feature. */ +@Generated +public class PurgeFeatureEntitiesResult { + /** Error encountered while purging this feature, if any. */ + @JsonProperty("error") + private DatabricksServiceExceptionWithDetailsProto error; + + /** Fully qualified name of the feature that was purged. */ + @JsonProperty("feature") + private String feature; + + /** State of the offline purge for this feature. */ + @JsonProperty("offline_state") + private PurgeFeatureEntitiesResultState offlineState; + + /** State of the online purge for this feature. */ + @JsonProperty("online_state") + private PurgeFeatureEntitiesResultState onlineState; + + public PurgeFeatureEntitiesResult setError(DatabricksServiceExceptionWithDetailsProto error) { + this.error = error; + return this; + } + + public DatabricksServiceExceptionWithDetailsProto getError() { + return error; + } + + public PurgeFeatureEntitiesResult setFeature(String feature) { + this.feature = feature; + return this; + } + + public String getFeature() { + return feature; + } + + public PurgeFeatureEntitiesResult setOfflineState(PurgeFeatureEntitiesResultState offlineState) { + this.offlineState = offlineState; + return this; + } + + public PurgeFeatureEntitiesResultState getOfflineState() { + return offlineState; + } + + public PurgeFeatureEntitiesResult setOnlineState(PurgeFeatureEntitiesResultState onlineState) { + this.onlineState = onlineState; + return this; + } + + public PurgeFeatureEntitiesResultState getOnlineState() { + return onlineState; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + PurgeFeatureEntitiesResult that = (PurgeFeatureEntitiesResult) o; + return Objects.equals(error, that.error) + && Objects.equals(feature, that.feature) + && Objects.equals(offlineState, that.offlineState) + && Objects.equals(onlineState, that.onlineState); + } + + @Override + public int hashCode() { + return Objects.hash(error, feature, offlineState, onlineState); + } + + @Override + public String toString() { + return new ToStringer(PurgeFeatureEntitiesResult.class) + .add("error", error) + .add("feature", feature) + .add("offlineState", offlineState) + .add("onlineState", onlineState) + .toString(); + } +} diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/PurgeFeatureEntitiesResultState.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/PurgeFeatureEntitiesResultState.java new file mode 100644 index 000000000..d1dd554cd --- /dev/null +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/PurgeFeatureEntitiesResultState.java @@ -0,0 +1,13 @@ +// Code generated from OpenAPI specs by Databricks SDK Generator. DO NOT EDIT. + +package com.databricks.sdk.service.ml; + +import com.databricks.sdk.support.Generated; + +/** Terminal state of a purge for one store type. */ +@Generated +public enum PurgeFeatureEntitiesResultState { + FAILED, + NOT_APPLICABLE, + SUCCEEDED, +}