worryg0d commented on issue #1746:
URL:
https://github.com/apache/cassandra-gocql-driver/issues/1746#issuecomment-2609405028
Hello. I guess I successfully reproduced it. I used the code provided by
@testisnullus and adjusted it a bit to run on Scylla 6.0.
I'm experiencing getting `applied = false` when executing batch
`ExecuteBatchCAS()` on an empty table, but the data is applied:
```
cqlsh> SELECT * from test.testkv ;
key | col | ts | val
------+-----+---------------------+--------------------------
key1 | l | 0 | 0x656e636f6465644c6f636b
key1 | d | 1737625396336730945 | 0x76616c756531
```
Also, I can't reproduce it on the latest Cassandra. The driver behaves the
way it should and returns `applied = true` when the data is actually applied
and `false` otherwise.
My Scylla setup:
```shell
docker run --name scylla-latest --hostname some-scylla -p 9042:9042 -d
scylladb/scylla --smp 1
```
My Cassandra setup:
```shell
docker run --name cassandra-latest -p 9043:9042 -d cassandra
```
The code I used to reproduce it:
```go
package main
import (
"fmt"
"log"
"time"
"github.com/gocql/gocql"
)
type Tx struct {
session *gocql.Session
pendingWrites map[string][]byte
readTime time.Time
table string
}
type TxnAborted struct{}
func (e *TxnAborted) Error() string {
return "Transaction aborted due to write conflict"
}
func createKeyspace(s *gocql.Session) error {
//if err := s.Query("CREATE KEYSPACE if not exists test WITH
replication = {'class': 'NetworkTopologyStrategy', 'replication_factor' :
1}").Exec(); err != nil {
// return fmt.Errorf("error creating keyspace: %w", err)
//}
// Scylla 6.0 specific code. LWT is not yet supported with tablets
if err := s.Query("CREATE KEYSPACE if not exists test WITH replication
= {'class': 'NetworkTopologyStrategy', 'replication_factor' : 1} AND TABLETS =
{'enabled': false}").Exec(); err != nil {
return fmt.Errorf("error creating keyspace: %w", err)
}
return nil
}
func createTable(s *gocql.Session) error {
// Table here won't be created because the keyspace is not specified...
//if err := s.Query("create table if not exists testkv (key text, col
text, ts bigint, val blob, primary key (key, col, ts)) with clustering order by
(col desc, ts desc)").Exec(); err != nil {
// return fmt.Errorf("error creating table: %w", err)
//}
if err := s.Query("create table if not exists test.testkv (key text,
col text, ts bigint, val blob, primary key (key, col, ts)) with clustering
order by (col desc, ts desc)").Exec(); err != nil {
return fmt.Errorf("error creating table: %w", err)
}
return nil
}
func (tx *Tx) ExecuteBatchTransaction() error {
b := tx.session.NewBatch(gocql.UnloggedBatch)
for key, val := range tx.pendingWrites {
b.Entries = append(b.Entries, gocql.BatchEntry{
//Stmt: fmt.Sprintf("insert into \"%s\" (key, ts, col,
val) values (?, 0, 'l', ?) if not exists", tx.table),
// DO NOT USE "\"\ for table name
Stmt: fmt.Sprintf("insert into %s (key, ts, col, val)
values (?, 0, 'l', ?) if not exists", tx.table),
Args: []any{key, []byte("encodedLock")},
})
// Insert the data record
b.Entries = append(b.Entries, gocql.BatchEntry{
//Stmt: fmt.Sprintf("insert into \"%s\" (key, ts, col,
val) values (?, ?, 'd', ?) if not exists", tx.table),
Stmt: fmt.Sprintf("insert into %s (key, ts, col, val)
values (?, ?, 'd', ?) if not exists", tx.table),
Args: []any{key, tx.readTime.UnixNano(), val},
})
}
//m := make(map[string]any)
applied, _, err := tx.session.ExecuteBatchCAS(b)
if err != nil {
return fmt.Errorf("error in ExecuteBatchCAS: %w", err)
}
fmt.Println("APPLIED?", applied)
//fmt.Println("MapExecuteBatchCAS:", m)
if !applied {
return fmt.Errorf("%w: prewrite not applied (conflict)",
&TxnAborted{})
}
fmt.Println(applied)
return nil
}
func main() {
// connect to the cluster
cluster := gocql.NewCluster("localhost:9042") // scylla
//cluster := gocql.NewCluster("localhost:9043") // cassandra
cluster.Consistency = gocql.Quorum
cluster.ProtoVersion = 4
cluster.ConnectTimeout = time.Second * 10
// Keyspace is being created when session is already initialized...
//cluster.Keyspace = "test"
session, err := cluster.CreateSession()
if err != nil {
log.Println(err)
return
}
defer session.Close()
// keyspace "test" is being created here
err = createKeyspace(session)
if err != nil {
fmt.Println("Keyspace failed:", err)
}
// table "testkv" in ks "test"
err = createTable(session)
if err != nil {
fmt.Println("Table failed:", err)
}
tx := Tx{
session: session,
pendingWrites: map[string][]byte{"key1": []byte("value1")},
readTime: time.Now(),
// It won't work because keyspace is not specified...
// Transaction failed: error in ExecuteBatchCAS: No keyspace
has been specified. USE a keyspace, or explicitly specify keyspace.tablename
//table: "testkv",
table: "test.testkv",
}
err = tx.ExecuteBatchTransaction()
if err != nil {
fmt.Println("Transaction failed:", err)
}
}
```
I'm not a Scylla expert, so I can't say if this is the driver issue or not.
However, at least there is a way to reproduce it.
Also, it is reproducable on
[scylladb/gocql](https://github.com/scylladb/gocql) fork as well.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]