Skip to content

Commit 23b1396

Browse files
feat: [discoveryengine] add document purge API (#9396)
- [ ] Regenerate this pull request now. docs: keep the API doc up-to-date with recent changes PiperOrigin-RevId: 528071547 Source-Link: https://togithub.com/googleapis/googleapis/commit/32e0dc1277f6b7a98cc2ed9ac29bf9c8770901ab Source-Link: https://togithub.com/googleapis/googleapis-gen/commit/f5843c4bc40eda236e54d363d794200f77de7d89 Copy-Tag: eyJwIjoiamF2YS1kaXNjb3ZlcnllbmdpbmUvLk93bEJvdC55YW1sIiwiaCI6ImY1ODQzYzRiYzQwZWRhMjM2ZTU0ZDM2M2Q3OTQyMDBmNzdkZTdkODkifQ==
1 parent bc46b1b commit 23b1396

File tree

33 files changed

+4706
-223
lines changed

33 files changed

+4706
-223
lines changed

java-discoveryengine/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ Java is a registered trademark of Oracle and/or its affiliates.
201201
[kokoro-badge-link-5]: http://storage.googleapis.com/cloud-devrel-public/java/badges/google-cloud-java/java11.html
202202
[stability-image]: https://img.shields.io/badge/stability-preview-yellow
203203
[maven-version-image]: https://img.shields.io/maven-central/v/com.google.cloud/google-cloud-discoveryengine.svg
204-
[maven-version-link]: https://central.sonatype.com/artifact/com.google.cloud/google-cloud-discoveryengine/0.11.0
204+
[maven-version-link]: https://central.sonatype.com/artifact/com.google.cloud/google-cloud-discoveryengine/0.12.0
205205
[authentication]: https://github.com/googleapis/google-cloud-java#authentication
206206
[auth-scopes]: https://developers.google.com/identity/protocols/oauth2/scopes
207207
[predefined-iam-roles]: https://cloud.google.com/iam/docs/understanding-roles#predefined_roles

java-discoveryengine/google-cloud-discoveryengine/src/main/java/com/google/cloud/discoveryengine/v1beta/DocumentServiceClient.java

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -997,6 +997,150 @@ public final UnaryCallable<ImportDocumentsRequest, Operation> importDocumentsCal
997997
return stub.importDocumentsCallable();
998998
}
999999

1000+
// AUTO-GENERATED DOCUMENTATION AND METHOD.
1001+
/**
1002+
* Permanently deletes all selected [Document][google.cloud.discoveryengine.v1beta.Document]s in a
1003+
* branch.
1004+
*
1005+
* <p>This process is asynchronous. Depending on the number of
1006+
* [Document][google.cloud.discoveryengine.v1beta.Document]s to be deleted, this operation can
1007+
* take hours to complete. Before the delete operation completes, some
1008+
* [Document][google.cloud.discoveryengine.v1beta.Document]s might still be returned by
1009+
* [DocumentService.GetDocument][google.cloud.discoveryengine.v1beta.DocumentService.GetDocument]
1010+
* or
1011+
* [DocumentService.ListDocuments][google.cloud.discoveryengine.v1beta.DocumentService.ListDocuments].
1012+
*
1013+
* <p>To get a list of the [Document][google.cloud.discoveryengine.v1beta.Document]s to be
1014+
* deleted, set
1015+
* [PurgeDocumentsRequest.force][google.cloud.discoveryengine.v1beta.PurgeDocumentsRequest.force]
1016+
* to false.
1017+
*
1018+
* <p>Sample code:
1019+
*
1020+
* <pre>{@code
1021+
* // This snippet has been automatically generated and should be regarded as a code template only.
1022+
* // It will require modifications to work:
1023+
* // - It may require correct/in-range values for request initialization.
1024+
* // - It may require specifying regional endpoints when creating the service client as shown in
1025+
* // https://cloud.google.com/java/docs/setup#configure_endpoints_for_the_client_library
1026+
* try (DocumentServiceClient documentServiceClient = DocumentServiceClient.create()) {
1027+
* PurgeDocumentsRequest request =
1028+
* PurgeDocumentsRequest.newBuilder()
1029+
* .setParent(
1030+
* BranchName.ofProjectLocationDataStoreBranchName(
1031+
* "[PROJECT]", "[LOCATION]", "[DATA_STORE]", "[BRANCH]")
1032+
* .toString())
1033+
* .setFilter("filter-1274492040")
1034+
* .setForce(true)
1035+
* .build();
1036+
* PurgeDocumentsResponse response = documentServiceClient.purgeDocumentsAsync(request).get();
1037+
* }
1038+
* }</pre>
1039+
*
1040+
* @param request The request object containing all of the parameters for the API call.
1041+
* @throws com.google.api.gax.rpc.ApiException if the remote call fails
1042+
*/
1043+
public final OperationFuture<PurgeDocumentsResponse, PurgeDocumentsMetadata> purgeDocumentsAsync(
1044+
PurgeDocumentsRequest request) {
1045+
return purgeDocumentsOperationCallable().futureCall(request);
1046+
}
1047+
1048+
// AUTO-GENERATED DOCUMENTATION AND METHOD.
1049+
/**
1050+
* Permanently deletes all selected [Document][google.cloud.discoveryengine.v1beta.Document]s in a
1051+
* branch.
1052+
*
1053+
* <p>This process is asynchronous. Depending on the number of
1054+
* [Document][google.cloud.discoveryengine.v1beta.Document]s to be deleted, this operation can
1055+
* take hours to complete. Before the delete operation completes, some
1056+
* [Document][google.cloud.discoveryengine.v1beta.Document]s might still be returned by
1057+
* [DocumentService.GetDocument][google.cloud.discoveryengine.v1beta.DocumentService.GetDocument]
1058+
* or
1059+
* [DocumentService.ListDocuments][google.cloud.discoveryengine.v1beta.DocumentService.ListDocuments].
1060+
*
1061+
* <p>To get a list of the [Document][google.cloud.discoveryengine.v1beta.Document]s to be
1062+
* deleted, set
1063+
* [PurgeDocumentsRequest.force][google.cloud.discoveryengine.v1beta.PurgeDocumentsRequest.force]
1064+
* to false.
1065+
*
1066+
* <p>Sample code:
1067+
*
1068+
* <pre>{@code
1069+
* // This snippet has been automatically generated and should be regarded as a code template only.
1070+
* // It will require modifications to work:
1071+
* // - It may require correct/in-range values for request initialization.
1072+
* // - It may require specifying regional endpoints when creating the service client as shown in
1073+
* // https://cloud.google.com/java/docs/setup#configure_endpoints_for_the_client_library
1074+
* try (DocumentServiceClient documentServiceClient = DocumentServiceClient.create()) {
1075+
* PurgeDocumentsRequest request =
1076+
* PurgeDocumentsRequest.newBuilder()
1077+
* .setParent(
1078+
* BranchName.ofProjectLocationDataStoreBranchName(
1079+
* "[PROJECT]", "[LOCATION]", "[DATA_STORE]", "[BRANCH]")
1080+
* .toString())
1081+
* .setFilter("filter-1274492040")
1082+
* .setForce(true)
1083+
* .build();
1084+
* OperationFuture<PurgeDocumentsResponse, PurgeDocumentsMetadata> future =
1085+
* documentServiceClient.purgeDocumentsOperationCallable().futureCall(request);
1086+
* // Do something.
1087+
* PurgeDocumentsResponse response = future.get();
1088+
* }
1089+
* }</pre>
1090+
*/
1091+
public final OperationCallable<
1092+
PurgeDocumentsRequest, PurgeDocumentsResponse, PurgeDocumentsMetadata>
1093+
purgeDocumentsOperationCallable() {
1094+
return stub.purgeDocumentsOperationCallable();
1095+
}
1096+
1097+
// AUTO-GENERATED DOCUMENTATION AND METHOD.
1098+
/**
1099+
* Permanently deletes all selected [Document][google.cloud.discoveryengine.v1beta.Document]s in a
1100+
* branch.
1101+
*
1102+
* <p>This process is asynchronous. Depending on the number of
1103+
* [Document][google.cloud.discoveryengine.v1beta.Document]s to be deleted, this operation can
1104+
* take hours to complete. Before the delete operation completes, some
1105+
* [Document][google.cloud.discoveryengine.v1beta.Document]s might still be returned by
1106+
* [DocumentService.GetDocument][google.cloud.discoveryengine.v1beta.DocumentService.GetDocument]
1107+
* or
1108+
* [DocumentService.ListDocuments][google.cloud.discoveryengine.v1beta.DocumentService.ListDocuments].
1109+
*
1110+
* <p>To get a list of the [Document][google.cloud.discoveryengine.v1beta.Document]s to be
1111+
* deleted, set
1112+
* [PurgeDocumentsRequest.force][google.cloud.discoveryengine.v1beta.PurgeDocumentsRequest.force]
1113+
* to false.
1114+
*
1115+
* <p>Sample code:
1116+
*
1117+
* <pre>{@code
1118+
* // This snippet has been automatically generated and should be regarded as a code template only.
1119+
* // It will require modifications to work:
1120+
* // - It may require correct/in-range values for request initialization.
1121+
* // - It may require specifying regional endpoints when creating the service client as shown in
1122+
* // https://cloud.google.com/java/docs/setup#configure_endpoints_for_the_client_library
1123+
* try (DocumentServiceClient documentServiceClient = DocumentServiceClient.create()) {
1124+
* PurgeDocumentsRequest request =
1125+
* PurgeDocumentsRequest.newBuilder()
1126+
* .setParent(
1127+
* BranchName.ofProjectLocationDataStoreBranchName(
1128+
* "[PROJECT]", "[LOCATION]", "[DATA_STORE]", "[BRANCH]")
1129+
* .toString())
1130+
* .setFilter("filter-1274492040")
1131+
* .setForce(true)
1132+
* .build();
1133+
* ApiFuture<Operation> future =
1134+
* documentServiceClient.purgeDocumentsCallable().futureCall(request);
1135+
* // Do something.
1136+
* Operation response = future.get();
1137+
* }
1138+
* }</pre>
1139+
*/
1140+
public final UnaryCallable<PurgeDocumentsRequest, Operation> purgeDocumentsCallable() {
1141+
return stub.purgeDocumentsCallable();
1142+
}
1143+
10001144
@Override
10011145
public final void close() {
10021146
stub.close();

java-discoveryengine/google-cloud-discoveryengine/src/main/java/com/google/cloud/discoveryengine/v1beta/DocumentServiceSettings.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,18 @@ public UnaryCallSettings<ImportDocumentsRequest, Operation> importDocumentsSetti
118118
return ((DocumentServiceStubSettings) getStubSettings()).importDocumentsOperationSettings();
119119
}
120120

121+
/** Returns the object with the settings used for calls to purgeDocuments. */
122+
public UnaryCallSettings<PurgeDocumentsRequest, Operation> purgeDocumentsSettings() {
123+
return ((DocumentServiceStubSettings) getStubSettings()).purgeDocumentsSettings();
124+
}
125+
126+
/** Returns the object with the settings used for calls to purgeDocuments. */
127+
public OperationCallSettings<
128+
PurgeDocumentsRequest, PurgeDocumentsResponse, PurgeDocumentsMetadata>
129+
purgeDocumentsOperationSettings() {
130+
return ((DocumentServiceStubSettings) getStubSettings()).purgeDocumentsOperationSettings();
131+
}
132+
121133
public static final DocumentServiceSettings create(DocumentServiceStubSettings stub)
122134
throws IOException {
123135
return new DocumentServiceSettings.Builder(stub.toBuilder()).build();
@@ -272,6 +284,18 @@ public UnaryCallSettings.Builder<ImportDocumentsRequest, Operation> importDocume
272284
return getStubSettingsBuilder().importDocumentsOperationSettings();
273285
}
274286

287+
/** Returns the builder for the settings used for calls to purgeDocuments. */
288+
public UnaryCallSettings.Builder<PurgeDocumentsRequest, Operation> purgeDocumentsSettings() {
289+
return getStubSettingsBuilder().purgeDocumentsSettings();
290+
}
291+
292+
/** Returns the builder for the settings used for calls to purgeDocuments. */
293+
public OperationCallSettings.Builder<
294+
PurgeDocumentsRequest, PurgeDocumentsResponse, PurgeDocumentsMetadata>
295+
purgeDocumentsOperationSettings() {
296+
return getStubSettingsBuilder().purgeDocumentsOperationSettings();
297+
}
298+
275299
@Override
276300
public DocumentServiceSettings build() throws IOException {
277301
return new DocumentServiceSettings(this);

java-discoveryengine/google-cloud-discoveryengine/src/main/java/com/google/cloud/discoveryengine/v1beta/gapic_metadata.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@
3737
"ListDocuments": {
3838
"methods": ["listDocuments", "listDocuments", "listDocuments", "listDocumentsPagedCallable", "listDocumentsCallable"]
3939
},
40+
"PurgeDocuments": {
41+
"methods": ["purgeDocumentsAsync", "purgeDocumentsOperationCallable", "purgeDocumentsCallable"]
42+
},
4043
"UpdateDocument": {
4144
"methods": ["updateDocument", "updateDocumentCallable"]
4245
}

java-discoveryengine/google-cloud-discoveryengine/src/main/java/com/google/cloud/discoveryengine/v1beta/stub/DocumentServiceStub.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@
3131
import com.google.cloud.discoveryengine.v1beta.ImportDocumentsResponse;
3232
import com.google.cloud.discoveryengine.v1beta.ListDocumentsRequest;
3333
import com.google.cloud.discoveryengine.v1beta.ListDocumentsResponse;
34+
import com.google.cloud.discoveryengine.v1beta.PurgeDocumentsMetadata;
35+
import com.google.cloud.discoveryengine.v1beta.PurgeDocumentsRequest;
36+
import com.google.cloud.discoveryengine.v1beta.PurgeDocumentsResponse;
3437
import com.google.cloud.discoveryengine.v1beta.UpdateDocumentRequest;
3538
import com.google.longrunning.Operation;
3639
import com.google.longrunning.stub.OperationsStub;
@@ -89,6 +92,15 @@ public UnaryCallable<ImportDocumentsRequest, Operation> importDocumentsCallable(
8992
throw new UnsupportedOperationException("Not implemented: importDocumentsCallable()");
9093
}
9194

95+
public OperationCallable<PurgeDocumentsRequest, PurgeDocumentsResponse, PurgeDocumentsMetadata>
96+
purgeDocumentsOperationCallable() {
97+
throw new UnsupportedOperationException("Not implemented: purgeDocumentsOperationCallable()");
98+
}
99+
100+
public UnaryCallable<PurgeDocumentsRequest, Operation> purgeDocumentsCallable() {
101+
throw new UnsupportedOperationException("Not implemented: purgeDocumentsCallable()");
102+
}
103+
92104
@Override
93105
public abstract void close();
94106
}

java-discoveryengine/google-cloud-discoveryengine/src/main/java/com/google/cloud/discoveryengine/v1beta/stub/DocumentServiceStubSettings.java

Lines changed: 77 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@
5656
import com.google.cloud.discoveryengine.v1beta.ImportDocumentsResponse;
5757
import com.google.cloud.discoveryengine.v1beta.ListDocumentsRequest;
5858
import com.google.cloud.discoveryengine.v1beta.ListDocumentsResponse;
59+
import com.google.cloud.discoveryengine.v1beta.PurgeDocumentsMetadata;
60+
import com.google.cloud.discoveryengine.v1beta.PurgeDocumentsRequest;
61+
import com.google.cloud.discoveryengine.v1beta.PurgeDocumentsResponse;
5962
import com.google.cloud.discoveryengine.v1beta.UpdateDocumentRequest;
6063
import com.google.common.collect.ImmutableList;
6164
import com.google.common.collect.ImmutableMap;
@@ -124,6 +127,10 @@ public class DocumentServiceStubSettings extends StubSettings<DocumentServiceStu
124127
private final OperationCallSettings<
125128
ImportDocumentsRequest, ImportDocumentsResponse, ImportDocumentsMetadata>
126129
importDocumentsOperationSettings;
130+
private final UnaryCallSettings<PurgeDocumentsRequest, Operation> purgeDocumentsSettings;
131+
private final OperationCallSettings<
132+
PurgeDocumentsRequest, PurgeDocumentsResponse, PurgeDocumentsMetadata>
133+
purgeDocumentsOperationSettings;
127134

128135
private static final PagedListDescriptor<ListDocumentsRequest, ListDocumentsResponse, Document>
129136
LIST_DOCUMENTS_PAGE_STR_DESC =
@@ -216,6 +223,18 @@ public UnaryCallSettings<ImportDocumentsRequest, Operation> importDocumentsSetti
216223
return importDocumentsOperationSettings;
217224
}
218225

226+
/** Returns the object with the settings used for calls to purgeDocuments. */
227+
public UnaryCallSettings<PurgeDocumentsRequest, Operation> purgeDocumentsSettings() {
228+
return purgeDocumentsSettings;
229+
}
230+
231+
/** Returns the object with the settings used for calls to purgeDocuments. */
232+
public OperationCallSettings<
233+
PurgeDocumentsRequest, PurgeDocumentsResponse, PurgeDocumentsMetadata>
234+
purgeDocumentsOperationSettings() {
235+
return purgeDocumentsOperationSettings;
236+
}
237+
219238
public DocumentServiceStub createStub() throws IOException {
220239
if (getTransportChannelProvider()
221240
.getTransportName()
@@ -329,6 +348,8 @@ protected DocumentServiceStubSettings(Builder settingsBuilder) throws IOExceptio
329348
deleteDocumentSettings = settingsBuilder.deleteDocumentSettings().build();
330349
importDocumentsSettings = settingsBuilder.importDocumentsSettings().build();
331350
importDocumentsOperationSettings = settingsBuilder.importDocumentsOperationSettings().build();
351+
purgeDocumentsSettings = settingsBuilder.purgeDocumentsSettings().build();
352+
purgeDocumentsOperationSettings = settingsBuilder.purgeDocumentsOperationSettings().build();
332353
}
333354

334355
/** Builder for DocumentServiceStubSettings. */
@@ -346,6 +367,11 @@ public static class Builder extends StubSettings.Builder<DocumentServiceStubSett
346367
private final OperationCallSettings.Builder<
347368
ImportDocumentsRequest, ImportDocumentsResponse, ImportDocumentsMetadata>
348369
importDocumentsOperationSettings;
370+
private final UnaryCallSettings.Builder<PurgeDocumentsRequest, Operation>
371+
purgeDocumentsSettings;
372+
private final OperationCallSettings.Builder<
373+
PurgeDocumentsRequest, PurgeDocumentsResponse, PurgeDocumentsMetadata>
374+
purgeDocumentsOperationSettings;
349375
private static final ImmutableMap<String, ImmutableSet<StatusCode.Code>>
350376
RETRYABLE_CODE_DEFINITIONS;
351377

@@ -405,6 +431,8 @@ protected Builder(ClientContext clientContext) {
405431
deleteDocumentSettings = UnaryCallSettings.newUnaryCallSettingsBuilder();
406432
importDocumentsSettings = UnaryCallSettings.newUnaryCallSettingsBuilder();
407433
importDocumentsOperationSettings = OperationCallSettings.newBuilder();
434+
purgeDocumentsSettings = UnaryCallSettings.newUnaryCallSettingsBuilder();
435+
purgeDocumentsOperationSettings = OperationCallSettings.newBuilder();
408436

409437
unaryMethodSettingsBuilders =
410438
ImmutableList.<UnaryCallSettings.Builder<?, ?>>of(
@@ -413,7 +441,8 @@ protected Builder(ClientContext clientContext) {
413441
createDocumentSettings,
414442
updateDocumentSettings,
415443
deleteDocumentSettings,
416-
importDocumentsSettings);
444+
importDocumentsSettings,
445+
purgeDocumentsSettings);
417446
initDefaults(this);
418447
}
419448

@@ -427,6 +456,8 @@ protected Builder(DocumentServiceStubSettings settings) {
427456
deleteDocumentSettings = settings.deleteDocumentSettings.toBuilder();
428457
importDocumentsSettings = settings.importDocumentsSettings.toBuilder();
429458
importDocumentsOperationSettings = settings.importDocumentsOperationSettings.toBuilder();
459+
purgeDocumentsSettings = settings.purgeDocumentsSettings.toBuilder();
460+
purgeDocumentsOperationSettings = settings.purgeDocumentsOperationSettings.toBuilder();
430461

431462
unaryMethodSettingsBuilders =
432463
ImmutableList.<UnaryCallSettings.Builder<?, ?>>of(
@@ -435,7 +466,8 @@ protected Builder(DocumentServiceStubSettings settings) {
435466
createDocumentSettings,
436467
updateDocumentSettings,
437468
deleteDocumentSettings,
438-
importDocumentsSettings);
469+
importDocumentsSettings,
470+
purgeDocumentsSettings);
439471
}
440472

441473
private static Builder createDefault() {
@@ -495,6 +527,11 @@ private static Builder initDefaults(Builder builder) {
495527
.setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("retry_policy_2_codes"))
496528
.setRetrySettings(RETRY_PARAM_DEFINITIONS.get("retry_policy_2_params"));
497529

530+
builder
531+
.purgeDocumentsSettings()
532+
.setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("retry_policy_1_codes"))
533+
.setRetrySettings(RETRY_PARAM_DEFINITIONS.get("retry_policy_1_params"));
534+
498535
builder
499536
.importDocumentsOperationSettings()
500537
.setInitialCallSettings(
@@ -519,6 +556,30 @@ private static Builder initDefaults(Builder builder) {
519556
.setTotalTimeout(Duration.ofMillis(300000L))
520557
.build()));
521558

559+
builder
560+
.purgeDocumentsOperationSettings()
561+
.setInitialCallSettings(
562+
UnaryCallSettings
563+
.<PurgeDocumentsRequest, OperationSnapshot>newUnaryCallSettingsBuilder()
564+
.setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("retry_policy_1_codes"))
565+
.setRetrySettings(RETRY_PARAM_DEFINITIONS.get("retry_policy_1_params"))
566+
.build())
567+
.setResponseTransformer(
568+
ProtoOperationTransformers.ResponseTransformer.create(PurgeDocumentsResponse.class))
569+
.setMetadataTransformer(
570+
ProtoOperationTransformers.MetadataTransformer.create(PurgeDocumentsMetadata.class))
571+
.setPollingAlgorithm(
572+
OperationTimedPollAlgorithm.create(
573+
RetrySettings.newBuilder()
574+
.setInitialRetryDelay(Duration.ofMillis(5000L))
575+
.setRetryDelayMultiplier(1.5)
576+
.setMaxRetryDelay(Duration.ofMillis(45000L))
577+
.setInitialRpcTimeout(Duration.ZERO)
578+
.setRpcTimeoutMultiplier(1.0)
579+
.setMaxRpcTimeout(Duration.ZERO)
580+
.setTotalTimeout(Duration.ofMillis(300000L))
581+
.build()));
582+
522583
return builder;
523584
}
524585

@@ -578,6 +639,20 @@ public UnaryCallSettings.Builder<ImportDocumentsRequest, Operation> importDocume
578639
return importDocumentsOperationSettings;
579640
}
580641

642+
/** Returns the builder for the settings used for calls to purgeDocuments. */
643+
public UnaryCallSettings.Builder<PurgeDocumentsRequest, Operation> purgeDocumentsSettings() {
644+
return purgeDocumentsSettings;
645+
}
646+
647+
/** Returns the builder for the settings used for calls to purgeDocuments. */
648+
@BetaApi(
649+
"The surface for use by generated code is not stable yet and may change in the future.")
650+
public OperationCallSettings.Builder<
651+
PurgeDocumentsRequest, PurgeDocumentsResponse, PurgeDocumentsMetadata>
652+
purgeDocumentsOperationSettings() {
653+
return purgeDocumentsOperationSettings;
654+
}
655+
581656
@Override
582657
public DocumentServiceStubSettings build() throws IOException {
583658
return new DocumentServiceStubSettings(this);

0 commit comments

Comments
 (0)