Skip to content

Commit 3a4652b

Browse files
authored
Merge branch 'main' into renovate/kubernetes-go
2 parents d49bf96 + a2f0b67 commit 3a4652b

File tree

119 files changed

+2907
-1573
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

119 files changed

+2907
-1573
lines changed
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
// Copyright 2025 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// https://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package deletes
16+
17+
// [START bigtable_streaming_and_batching_asyncio]
18+
19+
import (
20+
"context"
21+
"fmt"
22+
"io"
23+
24+
"cloud.google.com/go/bigtable"
25+
)
26+
27+
// streamingAndBatching starts a stream of data (reading rows), batches them, and then goes through the batch and deletes all the cells in column
28+
func streamingAndBatching(w io.Writer, projectID, instanceID string, tableName string) error {
29+
// projectID := "my-project-id"
30+
// instanceID := "my-instance-id"
31+
// tableName := "mobile-time-series"
32+
33+
ctx := context.Background()
34+
client, err := bigtable.NewClient(ctx, projectID, instanceID)
35+
if err != nil {
36+
return fmt.Errorf("bigtable.NewClient: %w", err)
37+
}
38+
defer client.Close()
39+
tbl := client.Open(tableName)
40+
41+
// Slices to hold the row keys and the corresponding mutations.
42+
var rowKeys []string
43+
var mutations []*bigtable.Mutation
44+
45+
// Read all rows from the table.
46+
err = tbl.ReadRows(ctx, bigtable.InfiniteRange(""), func(row bigtable.Row) bool {
47+
// For each row, create a mutation to delete the specified cell.
48+
mut := bigtable.NewMutation()
49+
mut.DeleteCellsInColumn("cell_plan", "data_plan_01gb")
50+
51+
// Append the row key and mutation to the slices.
52+
rowKeys = append(rowKeys, row.Key())
53+
mutations = append(mutations, mut)
54+
55+
// Continue processing rows.
56+
return true
57+
})
58+
if err != nil {
59+
return fmt.Errorf("tbl.ReadRows: %w", err)
60+
}
61+
62+
if len(mutations) == 0 {
63+
return nil
64+
}
65+
// If there are mutations to apply, apply them in a single bulk request.
66+
// ApplyBulk returns a slice of errors, one for each mutation.
67+
var errs []error
68+
if errs, err = tbl.ApplyBulk(ctx, rowKeys, mutations); err != nil {
69+
return fmt.Errorf("tbl.ApplyBulk: %w", err)
70+
}
71+
if errs != nil {
72+
// Log any individual errors that occurred during the bulk operation.
73+
var errorCount int
74+
for _, individualErr := range errs {
75+
if individualErr != nil {
76+
fmt.Fprintf(w, "Error applying mutation: %v\n", individualErr)
77+
errorCount++
78+
}
79+
}
80+
if errorCount > 0 {
81+
return fmt.Errorf("encountered %d error(s) out of %d mutations", errorCount, len(errs))
82+
}
83+
}
84+
85+
fmt.Fprintf(w, "Successfully deleted cells from all rows")
86+
return nil
87+
}
88+
89+
// [END bigtable_streaming_and_batching_asyncio]
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
// Copyright 2025 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// https://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package deletes
16+
17+
import (
18+
"bytes"
19+
"context"
20+
"fmt"
21+
"os"
22+
"strings"
23+
"testing"
24+
"time"
25+
26+
"cloud.google.com/go/bigtable"
27+
"github.com/GoogleCloudPlatform/golang-samples/internal/testutil"
28+
"github.com/google/uuid"
29+
"google.golang.org/grpc/codes"
30+
"google.golang.org/grpc/status"
31+
)
32+
33+
func TestStreamingAndBatching(t *testing.T) {
34+
ctx := context.Background()
35+
project := os.Getenv("GOLANG_SAMPLES_BIGTABLE_PROJECT")
36+
instance := os.Getenv("GOLANG_SAMPLES_BIGTABLE_INSTANCE")
37+
if project == "" || instance == "" {
38+
t.Fatal("Failed Bigtable integration test. Set GOLANG_SAMPLES_BIGTABLE_PROJECT and GOLANG_SAMPLES_BIGTABLE_INSTANCE.")
39+
}
40+
41+
// Create client
42+
adminClient, err := bigtable.NewAdminClient(ctx, project, instance)
43+
if err != nil {
44+
t.Fatalf("bigtable.NewAdminClient: %v", err)
45+
}
46+
47+
// Create table
48+
tableName := "mobile-time-series-" + uuid.New().String()[:8]
49+
if err := adminClient.DeleteTable(ctx, tableName); err != nil && status.Code(err) != codes.NotFound {
50+
t.Fatalf("adminClient.DeleteTable(%q): %v", tableName, err)
51+
}
52+
testutil.Retry(t, 10, 10*time.Second, func(r *testutil.R) {
53+
if err := adminClient.CreateTable(ctx, tableName); err != nil {
54+
if status.Code(err) == codes.AlreadyExists {
55+
adminClient.DeleteTable(ctx, tableName)
56+
time.Sleep(5 * time.Second)
57+
}
58+
r.Errorf("Could not create table %s: %v", tableName, err)
59+
}
60+
})
61+
if t.Failed() {
62+
return
63+
}
64+
defer adminClient.DeleteTable(ctx, tableName)
65+
66+
// Create column family
67+
columnFamilyName := "cell_plan"
68+
if err := adminClient.CreateColumnFamily(ctx, tableName, columnFamilyName); err != nil {
69+
t.Fatalf("CreateColumnFamily(%s): %v", columnFamilyName, err)
70+
}
71+
72+
// Write test data
73+
client, err := bigtable.NewClient(ctx, project, instance)
74+
if err != nil {
75+
t.Fatalf("bigtable.NewClient: %v", err)
76+
}
77+
defer client.Close()
78+
tbl := client.Open(tableName)
79+
rowKeys := []string{"phone#4c410523#20190501", "phone#5c10102#20190501"}
80+
muts := make([]*bigtable.Mutation, len(rowKeys))
81+
for i := range rowKeys {
82+
mut := bigtable.NewMutation()
83+
mut.Set(columnFamilyName, "data_plan_01gb", 0, []byte("true"))
84+
mut.Set(columnFamilyName, "data_plan_05gb", 0, []byte("true"))
85+
muts[i] = mut
86+
}
87+
if _, err := tbl.ApplyBulk(ctx, rowKeys, muts); err != nil {
88+
t.Fatalf("tbl.ApplyBulk: %v", err)
89+
}
90+
91+
// Run the function
92+
buf := new(bytes.Buffer)
93+
if err := streamingAndBatching(buf, project, instance, tableName); err != nil {
94+
t.Errorf("streamingAndBatching failed: %v", err)
95+
}
96+
97+
// Verify the output message
98+
if got, want := buf.String(), "Successfully deleted cells from all rows"; !strings.Contains(got, want) {
99+
t.Errorf("streamingAndBatching output got %q, want substring %q", got, want)
100+
}
101+
102+
// Verify that the cells were deleted
103+
for _, rowKey := range rowKeys {
104+
row, err := tbl.ReadRow(ctx, rowKey)
105+
if err != nil {
106+
t.Fatalf("tbl.ReadRow(%q): %v", rowKey, err)
107+
}
108+
if _, ok := row[columnFamilyName]; !ok {
109+
t.Errorf("row %q has no column family %q", rowKey, columnFamilyName)
110+
continue
111+
}
112+
for _, item := range row[columnFamilyName] {
113+
if item.Column == fmt.Sprintf("%s:data_plan_01gb", columnFamilyName) {
114+
t.Errorf("row %q still has cell %s:data_plan_01gb", rowKey, columnFamilyName)
115+
}
116+
}
117+
}
118+
}

genai/content_cache/contentcache_create_with_txt_gcs_pdf.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"encoding/json"
2222
"fmt"
2323
"io"
24+
"time"
2425

2526
genai "google.golang.org/genai"
2627
)
@@ -65,7 +66,7 @@ func createContentCache(w io.Writer) (string, error) {
6566
},
6667
},
6768
DisplayName: "example-cache",
68-
TTL: "86400s",
69+
TTL: time.Duration(time.Duration.Seconds(86400)),
6970
}
7071

7172
res, err := client.Caches.Create(ctx, modelName, config)

genai/content_cache/contentcache_update.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,26 +38,26 @@ func updateContentCache(w io.Writer, cacheName string) error {
3838

3939
// Update expire time using TTL
4040
resp, err := client.Caches.Update(ctx, cacheName, &genai.UpdateCachedContentConfig{
41-
TTL: "36000s",
41+
TTL: time.Duration(time.Duration.Seconds(36000)),
4242
})
4343
if err != nil {
4444
return fmt.Errorf("failed to update content cache exp. time with TTL: %w", err)
4545
}
4646

47-
fmt.Fprintf(w, "Cache expires in: %s\n", time.Until(*resp.ExpireTime))
47+
fmt.Fprintf(w, "Cache expires in: %s\n", time.Until(resp.ExpireTime))
4848
// Example response:
4949
// Cache expires in: 10h0m0.005875s
5050

5151
// Update expire time using specific time stamp
5252
inSevenDays := time.Now().Add(7 * 24 * time.Hour)
5353
resp, err = client.Caches.Update(ctx, cacheName, &genai.UpdateCachedContentConfig{
54-
ExpireTime: &inSevenDays,
54+
ExpireTime: inSevenDays,
5555
})
5656
if err != nil {
5757
return fmt.Errorf("failed to update content cache expire time: %w", err)
5858
}
5959

60-
fmt.Fprintf(w, "Cache expires in: %s\n", time.Until(*resp.ExpireTime))
60+
fmt.Fprintf(w, "Cache expires in: %s\n", time.Until(resp.ExpireTime))
6161
// Example response:
6262
// Cache expires in: 167h59m59.80327s
6363

genai/content_cache/contentcache_use_with_txt.go

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,8 @@ func useContentCacheWithTxt(w io.Writer, cacheName string) error {
4646
return fmt.Errorf("failed to use content cache to generate content: %w", err)
4747
}
4848

49-
respText, err := resp.Text()
50-
if err != nil {
51-
return fmt.Errorf("failed to convert model response to text: %w", err)
52-
}
49+
respText := resp.Text()
50+
5351
fmt.Fprintln(w, respText)
5452

5553
// Example response:

genai/controlled_generation/ctrlgen_with_enum_schema.go

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ func generateWithEnumSchema(w io.Writer) error {
3939
contents := []*genai.Content{
4040
{Parts: []*genai.Part{
4141
{Text: "What type of instrument is an oboe?"},
42-
}},
42+
}, Role: "user"},
4343
}
4444
config := &genai.GenerateContentConfig{
4545
ResponseMIMEType: "text/x.enum",
@@ -54,10 +54,8 @@ func generateWithEnumSchema(w io.Writer) error {
5454
return fmt.Errorf("failed to generate content: %w", err)
5555
}
5656

57-
respText, err := resp.Text()
58-
if err != nil {
59-
return fmt.Errorf("failed to convert model response to text: %w", err)
60-
}
57+
respText := resp.Text()
58+
6159
fmt.Fprintln(w, respText)
6260

6361
// Example response:

genai/controlled_generation/ctrlgen_with_nullable_schema.go

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ Finally, Saturday rounds off the week with sunny skies, a temperature of 80°F,
4949
contents := []*genai.Content{
5050
{Parts: []*genai.Part{
5151
{Text: prompt},
52-
}},
52+
},
53+
Role: "user"},
5354
}
5455
config := &genai.GenerateContentConfig{
5556
ResponseMIMEType: "application/json",
@@ -63,11 +64,11 @@ Finally, Saturday rounds off the week with sunny skies, a temperature of 80°F,
6364
Items: &genai.Schema{
6465
Type: "object",
6566
Properties: map[string]*genai.Schema{
66-
"Day": {Type: "string", Nullable: true},
67-
"Forecast": {Type: "string", Nullable: true},
68-
"Temperature": {Type: "integer", Nullable: true},
69-
"Humidity": {Type: "string", Nullable: true},
70-
"Wind Speed": {Type: "integer", Nullable: true},
67+
"Day": {Type: "string", Nullable: genai.Ptr(true)},
68+
"Forecast": {Type: "string", Nullable: genai.Ptr(true)},
69+
"Temperature": {Type: "integer", Nullable: genai.Ptr(true)},
70+
"Humidity": {Type: "string", Nullable: genai.Ptr(true)},
71+
"Wind Speed": {Type: "integer", Nullable: genai.Ptr(true)},
7172
},
7273
Required: []string{"Day", "Temperature", "Forecast", "Wind Speed"},
7374
},
@@ -81,10 +82,8 @@ Finally, Saturday rounds off the week with sunny skies, a temperature of 80°F,
8182
return fmt.Errorf("failed to generate content: %w", err)
8283
}
8384

84-
respText, err := resp.Text()
85-
if err != nil {
86-
return fmt.Errorf("failed to convert model response to text: %w", err)
87-
}
85+
respText := resp.Text()
86+
8887
fmt.Fprintln(w, respText)
8988

9089
// Example response:

genai/controlled_generation/ctrlgen_with_resp_schema.go

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,8 @@ func generateWithRespSchema(w io.Writer) error {
5757
contents := []*genai.Content{
5858
{Parts: []*genai.Part{
5959
{Text: "List a few popular cookie recipes."},
60-
}},
60+
},
61+
Role: "user"},
6162
}
6263
modelName := "gemini-2.0-flash-001"
6364

@@ -66,10 +67,8 @@ func generateWithRespSchema(w io.Writer) error {
6667
return fmt.Errorf("failed to generate content: %w", err)
6768
}
6869

69-
respText, err := resp.Text()
70-
if err != nil {
71-
return fmt.Errorf("failed to convert model response to text: %w", err)
72-
}
70+
respText := resp.Text()
71+
7372
fmt.Fprintln(w, respText)
7473

7574
// Example response:

genai/count_tokens/counttoken_compute_with_txt.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ func computeWithTxt(w io.Writer) error {
4040
contents := []*genai.Content{
4141
{Parts: []*genai.Part{
4242
{Text: "What's the longest word in the English language?"},
43-
}},
43+
},
44+
Role: "user"},
4445
}
4546

4647
resp, err := client.Models.ComputeTokens(ctx, modelName, contents, nil)

genai/count_tokens/counttoken_resp_with_txt.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ func generateTextAndCount(w io.Writer) error {
4040
contents := []*genai.Content{
4141
{Parts: []*genai.Part{
4242
{Text: "Why is the sky blue?"},
43-
}},
43+
},
44+
Role: "user"},
4445
}
4546

4647
resp, err := client.Models.GenerateContent(ctx, modelName, contents, nil)

0 commit comments

Comments
 (0)