agentsclimarketplace

Kora database cassandra

Skill kora-projects/kora-skills/plugins/kora-v1/skills/kora-database-cassandra

Agent Skills for Kora Framework — compile-time DI for Java/Kotlin backend development.

Install
npx -y skills add kora-projects/kora-skills --skill kora-database-cassandra

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Kora Cassandra/ScyllaDB repositories over the DataStax driver via CassandraDatabaseModule. Covers @Repository extends CassandraRepository, @Query CQL, @EntityCassandra DAO records, @Column/@Id, @UDT user-defined types, @Batch writes, @CassandraProfile per-method consistency, custom CassandraRowMapper/CassandraResultSetMapper/CassandraParameterColumnMapper, and async signatures (CompletionStage, Mono/Flux, Kotlin suspend/Flow). Use when adding a Cassandra repository, mapping rows or UDTs, tuning consistency/timeout under cassandra.basic.request, or wiring contact points and keyspace.

SKILL.md

10.9 KB, as published. Nobody here has run it

Kora Database Cassandra Skill

Focus: Cassandra/ScyllaDB distributed database integration using DataStax Java Driver 4.x.

Use for: High-write-throughput, horizontally-scalable NoSQL workloads with tunable consistency levels, time-series data, event sourcing, and distributed systems requiring eventual consistency.

Read this first when:

  • Adding a Cassandra repository with @Repository and CQL queries
  • Modeling entities with @EntityCassandra, @UDT for user-defined types
  • Configuring profile-based consistency levels and request timeouts
  • Implementing async signatures with CompletionStage, Reactor, or Kotlin Flow

Quick Start

1. Add Dependency

All Kora artifacts inherit their version from the kora-parent BOM; never pin individual ru.tinkoff.kora:* versions. Annotation processing is mandatory — without it no repository implementation is generated.

dependencies {
    koraBom platform("ru.tinkoff.kora:kora-parent:1.2.17")
    annotationProcessor "ru.tinkoff.kora:annotation-processors"   // Java
    // ksp "ru.tinkoff.kora:symbol-processors"                    // Kotlin (instead of annotationProcessor)

    implementation "ru.tinkoff.kora:database-cassandra"
    implementation "ru.tinkoff.kora:config-hocon"
    implementation "ru.tinkoff.kora:logging-logback"

    // Optional: only when repository methods return Mono/Flux
    implementation "io.projectreactor:reactor-core:3.6.18"
}

2. Enable Module

@KoraApp
public interface Application extends CassandraDatabaseModule {}

3. Define Entity

@Table("users")
@EntityCassandra
public record User(
    @Column("id") @Id UUID id,
    @Column("name") String name,
    @Column("email") String email,
    @Column("created_at") Instant createdAt,
    @Column("nickname") @Nullable String nickname
) {}

4. Create Repository

@Repository
public interface UserRepository extends CassandraRepository {
    
    @Query("SELECT * FROM users WHERE id = :id")
    @Nullable
    User findById(UUID id);
    
    @Query("SELECT * FROM users")
    List<User> findAll();
    
    @Query("INSERT INTO users (id, name, email, created_at) VALUES (:user.id, :user.name, :user.email, :user.createdAt)")
    void insert(User user);
    
    @Query("DELETE FROM users WHERE id = :id")
    void deleteById(UUID id);
}

Entity parameter binding: when a method parameter is an entity object, each column is bound through the dotted accessor :param.field (e.g. :user.id), not a bare :id. A bare :id only resolves when id is itself the name of a method parameter (as in findById(UUID id)).

5. Configure Connection

cassandra {
    auth {
        login = ${CASSANDRA_USER}
        password = ${CASSANDRA_PASS}
    }
    basic {
        contactPoints = ["localhost:9042"]
        dc = "datacenter1"
        sessionKeyspace = "mykeyspace"
        request {
            timeout = 5s
        }
    }
    telemetry {
        logging {
            enabled = true
        }
    }
}

Basic CRUD Patterns

Insert

@Query("INSERT INTO users (id, name, email) VALUES (:user.id, :user.name, :user.email)")
void insert(User user);

// Batch insert: one single-row INSERT bound to entity fields, parameter marked @Batch
@Query("INSERT INTO users (id, name, email) VALUES (:user.id, :user.name, :user.email)")
void insertBatch(@Batch List<User> user);

// Conditional insert (LWT)
@Query("INSERT INTO users (id, name) VALUES (:user.id, :user.name) IF NOT EXISTS")
boolean insertIfNotExists(User user);

Select

@Query("SELECT * FROM users WHERE id = :id")
@Nullable
User findById(UUID id);

@Query("SELECT * FROM users WHERE id IN :ids")
List<User> findByIds(List<UUID> ids);

@Query("SELECT * FROM users LIMIT 100")
List<User> findFirst100();

Update

@Query("UPDATE users SET name = :user.name, email = :user.email WHERE id = :user.id")
void update(User user);

// Conditional update (LWT)
@Query("UPDATE users SET email = :email WHERE id = :id IF email = :oldEmail")
boolean updateIfEmailMatches(UUID id, String email, String oldEmail);

Delete

@Query("DELETE FROM users WHERE id = :id")
void deleteById(UUID id);

@Query("TRUNCATE users")
void deleteAll();

Async Signatures

CompletionStage (Recommended)

@Query("SELECT * FROM users WHERE id = :id")
CompletableFuture<User> findByIdAsync(UUID id);

@Query("INSERT INTO users (id, name) VALUES (:user.id, :user.name)")
CompletionStage<Void> insertAsync(User user);

Project Reactor

@Query("SELECT * FROM users WHERE id = :id")
Mono<User> findByIdReactive(UUID id);

@Query("SELECT * FROM users")
Flux<User> findAllReactive();

Kotlin Coroutines

@Query("SELECT * FROM users WHERE id = :id")
suspend fun findByIdAsync(id: UUID): User?

@Query("SELECT * FROM users")
fun findAllFlow(): Flow<User>

UDT Support

@UDT
public record AddressUDT(
    @Column("street") String street,
    @Column("city") String city,
    @Column("zipCode") String zipCode
) {}

@Table("users")
@EntityCassandra
public record User(
    @Column("id") @Id UUID id,
    @Column("name") String name,
    @Column("address") AddressUDT address
) {}

Profile-Based Consistency

All request-level tuning (consistency, timeout, page size) lives under basic.request. A profile overrides any basic.request.* (and advanced.*) key for the queries that reference it.

Configuration

cassandra {
    basic {
        request {
            consistency = "QUORUM"        // default consistency for all queries
            serialConsistency = "SERIAL"  // consistency for lightweight transactions
            timeout = "5s"
        }
    }
    profiles {
        analytics {
            basic.request.consistency = "ONE"
            basic.request.timeout = "30s"
        }
        critical {
            basic.request.consistency = "ALL"
            basic.request.timeout = "5s"
        }
    }
}

Using Profiles

@CassandraProfile targets methods only (@Target(ElementType.METHOD)). It cannot be placed on the repository interface — apply it per @Query method.

@Repository
public interface EventRepository extends CassandraRepository {

    @CassandraProfile("analytics")
    @Query("SELECT * FROM events WHERE type = :type ALLOW FILTERING")
    List<Event> findByType(String type);
}

Assets

Entity Templates

TemplateLanguageDescription
cassandra-entity-single-id.java.templateJavaEntity with single-field ID
cassandra-entity-single-id.kt.templateKotlinData class with single-field ID
cassandra-entity-composite-id.java.templateJavaEntity with composite partition key
cassandra-entity-composite-id.kt.templateKotlinData class with composite key
cassandra-entity-with-udt.java.templateJavaEntity with UDT and List<UDT>

Repository Templates

TemplateLanguageDescription
cassandra-crud-single-id-repository.java.templateJavaCRUD with LWT support
cassandra-crud-single-id-repository.kt.templateKotlinKotlin CRUD repository
cassandra-crud-composite-id-repository.java.templateJavaCRUD for composite key
cassandra-crud-composite-id-repository.kt.templateKotlinKotlin composite key CRUD
cassandra-async-repository.java.templateJavaCompletionStage async
cassandra-async-repository.kt.templateKotlinKotlin async
cassandra-lwt-repository.java.templateJavaLightweight transactions
cassandra-lwt-repository.kt.templateKotlinKotlin LWT
cassandra-kotlin-coroutine-repository.kt.templateKotlinKotlin coroutines + Flow

UDT Templates

TemplateLanguageDescription
cassandra-udt.java.templateJavaBasic UDT (Address example)
cassandra-udt.kt.templateKotlinKotlin UDT data class
cassandra-nested-udt.java.templateJavaNested UDT structure

Reference Documents

DocumentDescription
CQL Repository Reference@EntityCassandra, CQL queries, custom mappers, return types
UDT Mapping Reference@UDT, nested types, collections of UDTs
Consistency ReferenceConsistency levels, profiles, retry policies
Async Patterns ReferenceCompletionStage, Reactor, Kotlin Flow
Cassandra Config ReferenceConnection, timeouts, load balancing, multiple keyspaces

Best Practices

  1. Use @EntityCassandra on DAO records — generates the Cassandra row and result-set mappers eagerly at compile time instead of in a late generation round.
  2. Add @Column to every component — makes the CQL column name explicit (e.g. Java createdAt -> column created_at).
  3. @Id is optional — Cassandra needs no special primary-key marker; add @Id only when you use SQL macros.
  4. Use @Nullable, not Optional — for nullable single-row return values.
  5. Extend CassandraRepository — required base interface for the generator.
  6. Keep DTOs and DAOs separate — HTTP @Json DTOs are not Cassandra entities.
  7. Apply @CassandraProfile per method — separate analytics from critical reads.
  8. Model tables from query patterns — avoid unbounded SELECT ... FROM table scans in production.

Common Pitfalls

SymptomFix
@CassandraProfile rejected on the interfaceIt is @Target(METHOD) — move it onto each @Query method.
Config key basic.consistency ignoredConsistency lives under basic.request.consistency.
Profile timeout ignored (requestTimeout)Override basic.request.timeout inside the profile, not a flat key.
Complex field not mappedNested types need @UDT; collections of UDTs need FROZEN in CQL.
Required field is not nullable but row has nullAdd @Nullable to the optional record component.
Repository method not generatedAnnotation processor missing, or the interface does not extend CassandraRepository.

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.