This is an automated email from the ASF dual-hosted git repository.

dcapwell pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/cassandra-easy-stress.git


The following commit(s) were added to refs/heads/main by this push:
     new e4ca160  Make sure the parquet file is compressed and uses the v2 
format (#109)
e4ca160 is described below

commit e4ca160d6183a08157ad9f118a9d2136b211836d
Author: dcapwell <[email protected]>
AuthorDate: Tue Oct 20 23:18:57 2026 -0700

    Make sure the parquet file is compressed and uses the v2 format (#109)
---
 CLAUDE.md                                          | 10 ++++
 build.gradle.kts                                   |  8 +++
 .../easystress/collector/ParquetCollector.kt       | 13 ++++-
 .../easystress/collector/ParquetCollectorTest.kt   | 63 ++++++++++++++++++++++
 4 files changed, 93 insertions(+), 1 deletion(-)

diff --git a/CLAUDE.md b/CLAUDE.md
index c7af45e..e63ce2c 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -13,6 +13,16 @@ For comprehensive testing documentation, see the [Testing 
section in README.md](
 - Format code: `./gradlew ktlintFormat`
 - Check formatting: `./gradlew ktlintCheck`
 - Generate docs: `./gradlew docs`
+- Fast pre-PR checks: `./gradlew preflight` (ktlintCheck, detekt, test, 
distTar)
+
+## Before declaring work done (required)
+
+Run `./gradlew ktlintFormat` then `./gradlew preflight` and fix any failures. 
This covers
+the cheap CI jobs: ktlint, detekt, unit tests, and `distTar`. The slower 
per-version matrix
+(test40/test41/test50 on JDK 21 and 25) is left to CI; no need to run it 
locally.
+
+When adding a dependency, confirm it is the maintained artifact and that it 
lands in the
+distribution (`distTar`).
 
 ## Code Style Guidelines
 - Kotlin version: 1.9.0
diff --git a/build.gradle.kts b/build.gradle.kts
index 2d38a58..5ae2508 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -351,3 +351,11 @@ tasks.withType<DetektCreateBaselineTask>().configureEach {
 tasks.withType<ShadowJar>().configureEach {
     isZip64 = true
 }
+
+// Fast local checks mirroring the cheap CI jobs (lint, detekt, unit tests, 
distTar).
+// The slower per-version matrix (test40/test41/test50) is left to CI.
+tasks.register("preflight") {
+    group = "verification"
+    description = "Run fast CI-equivalent checks before sending a PR"
+    dependsOn("ktlintCheck", "detekt", "test", "distTar")
+}
diff --git 
a/src/main/kotlin/org/apache/cassandra/easystress/collector/ParquetCollector.kt 
b/src/main/kotlin/org/apache/cassandra/easystress/collector/ParquetCollector.kt
index 1b54476..959681b 100644
--- 
a/src/main/kotlin/org/apache/cassandra/easystress/collector/ParquetCollector.kt
+++ 
b/src/main/kotlin/org/apache/cassandra/easystress/collector/ParquetCollector.kt
@@ -4,10 +4,12 @@ import com.datastax.oss.driver.api.core.cql.AsyncResultSet
 import com.google.common.base.Throwables
 import org.apache.cassandra.easystress.Either
 import org.apache.hadoop.fs.Path
+import org.apache.parquet.column.ParquetProperties
 import org.apache.parquet.example.data.Group
 import org.apache.parquet.example.data.simple.SimpleGroupFactory
 import org.apache.parquet.hadoop.ParquetWriter
 import org.apache.parquet.hadoop.example.ExampleParquetWriter
+import org.apache.parquet.hadoop.metadata.CompressionCodecName
 import org.apache.parquet.schema.MessageTypeParser
 import java.io.File
 import java.util.concurrent.TimeUnit
@@ -46,7 +48,16 @@ class ParquetCollector(
                         "}",
                 )
             groupFactory = SimpleGroupFactory(schema)
-            writer = 
ExampleParquetWriter.builder(path).withType(schema).build()
+            // Defaults are UNCOMPRESSED + PARQUET_1_0 (PLAIN int64), which 
for long runs produces multi-GB files.
+            // ZSTD + PARQUET_2_0 (DELTA_BINARY_PACKED for the time/duration 
columns) is ~3x smaller with the same
+            // schema and values.
+            writer =
+                ExampleParquetWriter
+                    .builder(path)
+                    .withType(schema)
+                    .withCompressionCodec(CompressionCodecName.ZSTD)
+                    
.withWriterVersion(ParquetProperties.WriterVersion.PARQUET_2_0)
+                    .build()
         }
 
         override fun write(event: Event) {
diff --git 
a/src/test/kotlin/org/apache/cassandra/easystress/collector/ParquetCollectorTest.kt
 
b/src/test/kotlin/org/apache/cassandra/easystress/collector/ParquetCollectorTest.kt
index 6b7824b..2b97ac7 100644
--- 
a/src/test/kotlin/org/apache/cassandra/easystress/collector/ParquetCollectorTest.kt
+++ 
b/src/test/kotlin/org/apache/cassandra/easystress/collector/ParquetCollectorTest.kt
@@ -1,12 +1,24 @@
 package org.apache.cassandra.easystress.collector
 
 import com.datastax.oss.driver.api.core.CqlSession
+import com.datastax.oss.driver.api.core.cql.AsyncResultSet
+import com.datastax.oss.driver.api.core.cql.BoundStatement
 import com.google.common.io.Files
 import io.mockk.mockk
 import org.apache.cassandra.easystress.Context
+import org.apache.cassandra.easystress.Either
 import org.apache.cassandra.easystress.Metrics
 import org.apache.cassandra.easystress.commands.Run
 import org.apache.cassandra.easystress.generators.Registry
+import org.apache.cassandra.easystress.workloads.Operation
+import org.apache.hadoop.conf.Configuration
+import org.apache.parquet.column.Encoding
+import org.apache.parquet.example.data.Group
+import org.apache.parquet.hadoop.ParquetFileReader
+import org.apache.parquet.hadoop.ParquetReader
+import org.apache.parquet.hadoop.example.GroupReadSupport
+import org.apache.parquet.hadoop.metadata.CompressionCodecName
+import org.apache.parquet.hadoop.util.HadoopInputFile
 import org.assertj.core.api.Assertions
 import org.assertj.core.api.Condition
 import org.junit.jupiter.api.Test
@@ -51,6 +63,57 @@ internal class ParquetCollectorTest {
         )
     }
 
+    @Test
+    fun usesZstdAndV2Encodings() {
+        val file = tempDir!!.resolve("rawlog.parquet").toFile()
+        val op = Operation.SelectStatement(mockk<BoundStatement>())
+        val writer = ParquetCollector.ParquetTableWriter(file)
+        val rows = 100
+        for (i in 0 until rows) {
+            writer.write(
+                AsyncCollector.Event(
+                    op,
+                    Either.Left(mockk<AsyncResultSet>()),
+                    op.createdAtNanos + i,
+                    op.createdAtNanos + 1_000 + i * 2L,
+                ),
+            )
+        }
+        writer.close()
+
+        val path =
+            org.apache.hadoop.fs
+                .Path(file.toURI())
+        val conf = Configuration()
+        ParquetFileReader.open(HadoopInputFile.fromPath(path, conf)).use { 
reader ->
+            val columns = reader.footer.blocks.flatMap { it.columns }
+            Assertions.assertThat(columns).isNotEmpty
+            Assertions.assertThat(columns.map { it.codec 
}).containsOnly(CompressionCodecName.ZSTD)
+            val int64Encodings =
+                columns
+                    .filter { it.path.toDotString().endsWith("_ms") || 
it.path.toDotString().endsWith("_ns") }
+                    .flatMap { it.encodings }
+            
Assertions.assertThat(int64Encodings).contains(Encoding.DELTA_BINARY_PACKED)
+        }
+
+        // semantics must not change: same columns, same values
+        val read = mutableListOf<Group>()
+        ParquetReader.builder(GroupReadSupport(), 
path).withConf(conf).build().use { reader ->
+            while (true) {
+                read.add(reader.read() ?: break)
+            }
+        }
+        Assertions.assertThat(read).hasSize(rows)
+        read.forEachIndexed { i, g ->
+            Assertions.assertThat(g.getString("operation", 
0)).isEqualTo("Select")
+            Assertions.assertThat(g.getBoolean("success", 0)).isTrue
+            Assertions.assertThat(g.getString("failure_reason", 0)).isEmpty()
+            Assertions.assertThat(g.getLong("request_start_time_ms", 
0)).isEqualTo(op.createdAtMillis)
+            Assertions.assertThat(g.getLong("request_duration_ns", 
0)).isEqualTo(1_000 + i * 2L)
+            Assertions.assertThat(g.getLong("service_duration_ns", 
0)).isEqualTo(1_000 + i * 2L - i)
+        }
+    }
+
     companion object {
         val ctx =
             Context(


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to