Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package rqlite for openSUSE:Factory checked 
in at 2026-01-13 21:23:44
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/rqlite (Old)
 and      /work/SRC/openSUSE:Factory/.rqlite.new.1928 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "rqlite"

Tue Jan 13 21:23:44 2026 rev:40 rq:1326495 version:9.3.14

Changes:
--------
--- /work/SRC/openSUSE:Factory/rqlite/rqlite.changes    2026-01-08 
15:28:28.791685656 +0100
+++ /work/SRC/openSUSE:Factory/.rqlite.new.1928/rqlite.changes  2026-01-13 
21:24:10.934232111 +0100
@@ -1,0 +2,8 @@
+Sat Jan 10 08:28:49 UTC 2026 - Andreas Stieger <[email protected]>
+
+- Update to version 9.3.14:
+  * Increase WAL Checkpoint busy timeout to 250ms
+  * Implement a must-checkpoint-WAL after multiple failures policy
+  * fix SQL comment handling in CLI
+
+-------------------------------------------------------------------

Old:
----
  rqlite-9.3.11.tar.xz

New:
----
  rqlite-9.3.14.tar.xz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ rqlite.spec ++++++
--- /var/tmp/diff_new_pack.fYB0ma/_old  2026-01-13 21:24:11.694263480 +0100
+++ /var/tmp/diff_new_pack.fYB0ma/_new  2026-01-13 21:24:11.694263480 +0100
@@ -17,7 +17,7 @@
 
 
 Name:           rqlite
-Version:        9.3.11
+Version:        9.3.14
 Release:        0
 Summary:        Distributed relational database built on SQLite
 License:        MIT

++++++ _service ++++++
--- /var/tmp/diff_new_pack.fYB0ma/_old  2026-01-13 21:24:11.746265627 +0100
+++ /var/tmp/diff_new_pack.fYB0ma/_new  2026-01-13 21:24:11.754265957 +0100
@@ -3,7 +3,7 @@
     <param name="url">https://github.com/rqlite/rqlite.git</param>
     <param name="scm">git</param>
     <param name="exclude">.git</param>
-    <param name="revision">v9.3.11</param>
+    <param name="revision">v9.3.14</param>
     <param name="versionformat">@PARENT_TAG@</param>
     <param name="changesgenerate">enable</param>
     <param name="versionrewrite-pattern">v(.*)</param>

++++++ _servicedata ++++++
--- /var/tmp/diff_new_pack.fYB0ma/_old  2026-01-13 21:24:11.786267278 +0100
+++ /var/tmp/diff_new_pack.fYB0ma/_new  2026-01-13 21:24:11.790267443 +0100
@@ -1,7 +1,7 @@
 <servicedata>
   <service name="tar_scm">
     <param name="url">https://github.com/rqlite/rqlite.git</param>
-    <param 
name="changesrevision">9589c3caa5da939fb3e2bbb143e0b06b301ac1dd</param>
+    <param 
name="changesrevision">369be06aee046ad4248b3d70f169ca8b37188b6a</param>
   </service>
 </servicedata>
 (No newline at EOF)

++++++ rqlite-9.3.11.tar.xz -> rqlite-9.3.14.tar.xz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/rqlite-9.3.11/CHANGELOG.md 
new/rqlite-9.3.14/CHANGELOG.md
--- old/rqlite-9.3.11/CHANGELOG.md      2026-01-07 05:16:04.000000000 +0100
+++ new/rqlite-9.3.14/CHANGELOG.md      2026-01-09 08:01:54.000000000 +0100
@@ -1,3 +1,16 @@
+## v9.3.14 (January 9th 2025)
+### Implementation changes and bug fixes
+- [PR #2444](https://github.com/rqlite/rqlite/pull/2444): Increase WAL 
Checkpoint busy timeout to 250ms.
+- [PR #2445](https://github.com/rqlite/rqlite/pull/2445): Implement a 
must-checkpoint-WAL after multiple failures policy.
+
+## v9.3.13 (January 8th 2026)
+### Implementation changes and bug fixes
+- [PR #2443](https://github.com/rqlite/rqlite/pull/2443): Don't scan for rows 
if zero columns returned by query. Fixes issue 
[#2441](https://github.com/rqlite/rqlite/issues/2441).
+
+## v9.3.12 (January 8th 2026)
+### Implementation changes and bug fixes
+- [PR #2442](https://github.com/rqlite/rqlite/pull/2442): Remove inadvertently 
committed debug statement.
+
 ## v9.3.11 (January 6th 2026)
 ### Implementation changes and bug fixes
 - [PR #2438](https://github.com/rqlite/rqlite/pull/2438): Correctly handle 
`EXPLAIN QUERY PLAN` for mutations. Fixes issue 
[#2433](https://github.com/rqlite/rqlite/issues/2433).
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/rqlite-9.3.11/db/db.go new/rqlite-9.3.14/db/db.go
--- old/rqlite-9.3.11/db/db.go  2026-01-07 05:16:04.000000000 +0100
+++ new/rqlite-9.3.14/db/db.go  2026-01-09 08:01:54.000000000 +0100
@@ -25,11 +25,12 @@
 )
 
 const (
-       SQLiteHeaderSize = 32
-       bkDelay          = 250
-       durToOpenLog     = 2 * time.Second
-       OptimizeDefault  = 0xFFFE
-       OptimizeAll      = 0x10002
+       SQLiteHeaderSize      = 32
+       bkDelay               = 250 * time.Millisecond
+       checkpointBusyTimeout = 250 * time.Millisecond
+       durToOpenLog          = 2 * time.Second
+       OptimizeDefault       = 0xFFFE
+       OptimizeAll           = 0x10002
 )
 
 const (
@@ -659,7 +660,7 @@
 // Checkpoint checkpoints the WAL file. If the WAL file is not enabled, this
 // function is a no-op.
 func (db *DB) Checkpoint(mode CheckpointMode) (*CheckpointMeta, error) {
-       return db.CheckpointWithTimeout(mode, 1000)
+       return db.CheckpointWithTimeout(mode, checkpointBusyTimeout)
 }
 
 // CheckpointWithTimeout performs a WAL checkpoint. If the checkpoint does not
@@ -1238,7 +1239,7 @@
 
        dest := make([]any, len(columns))
        ptrs := make([]any, len(dest))
-       for rs.Next() {
+       for rs.Next() && (len(columns) > 0 || forceStall) {
                dest := dest[:]
                ptrs := ptrs[:]
                for i := range ptrs {
@@ -1741,7 +1742,7 @@
                        break
                }
                stats.Add(numBackupSleeps, 1)
-               time.Sleep(bkDelay * time.Millisecond)
+               time.Sleep(bkDelay)
        }
        return bk.Finish()
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/rqlite-9.3.11/db/db_common_test.go 
new/rqlite-9.3.14/db/db_common_test.go
--- old/rqlite-9.3.11/db/db_common_test.go      2026-01-07 05:16:04.000000000 
+0100
+++ new/rqlite-9.3.14/db/db_common_test.go      2026-01-09 08:01:54.000000000 
+0100
@@ -106,6 +106,70 @@
        }
 }
 
+func Test_SQL_Comments(t *testing.T) {
+       db, path := mustCreateOnDiskDatabaseWAL()
+       defer os.Remove(path)
+       defer db.Close()
+
+       for _, tt := range []struct {
+               name string
+               sql  string
+               exp  string
+       }{
+               {
+                       name: "single line comment",
+                       sql:  "-- This is a comment\nCREATE TABLE foo (id 
INTEGER NOT NULL PRIMARY KEY, name TEXT)",
+                       exp:  `[{}]`,
+               },
+               {
+                       name: "multi-line comment",
+                       sql:  "/* This is a\nmulti-line comment */\nCREATE 
TABLE bar (id INTEGER NOT NULL PRIMARY KEY, name TEXT)",
+                       exp:  `[{}]`,
+               },
+       } {
+               r, err := db.ExecuteStringStmt(tt.sql)
+               if err != nil {
+                       t.Fatalf("failed to create table with %s: %s", tt.name, 
err.Error())
+               }
+               if exp, got := tt.exp, asJSON(r); exp != got {
+                       t.Fatalf("unexpected results for query with %s, 
expected %s, got %s", tt.name, exp, got)
+               }
+       }
+
+       for _, tt := range []struct {
+               name string
+               sql  string
+               exp  string
+       }{
+               {
+                       name: "comment only",
+                       sql:  "-----",
+                       exp:  `[{}]`,
+               },
+               {
+                       name: "multi-line comment only",
+                       sql:  "/* This is a\nmulti-line comment */",
+                       exp:  `[{}]`,
+               },
+       } {
+               r, err := db.QueryStringStmt(tt.sql)
+               if err != nil {
+                       t.Fatalf("failed to query with comment %s: %s", 
tt.name, err.Error())
+               }
+               if exp, got := tt.exp, asJSON(r); exp != got {
+                       t.Fatalf("unexpected results for query with %s, 
expected %s, got %s", tt.name, exp, got)
+               }
+       }
+
+       req, err := db.RequestStringStmts([]string{"-----", "SELECT * FROM 
qux"})
+       if err != nil {
+               t.Fatalf("failed to request empty statements: %s", err.Error())
+       }
+       if exp, got := `[{},{"error":"no such table: qux"}]`, asJSON(req); exp 
!= got {
+               t.Fatalf(`unexpected results for request exp: %s got: %s`, exp, 
got)
+       }
+}
+
 func Test_DB_ExplainSelect(t *testing.T) {
        db, path := mustCreateOnDiskDatabaseWAL()
        defer os.Remove(path)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/rqlite-9.3.11/http/service.go 
new/rqlite-9.3.14/http/service.go
--- old/rqlite-9.3.11/http/service.go   2026-01-07 05:16:04.000000000 +0100
+++ new/rqlite-9.3.14/http/service.go   2026-01-09 08:01:54.000000000 +0100
@@ -1444,7 +1444,6 @@
        stats.Add(numQueryStmtsRx, int64(len(queries)))
 
        if !qp.NoParse() {
-               fmt.Println("Processing queries:", queries)
                if err := sql.Process(queries, qp.NoRewriteRandom(), 
!qp.NoRewriteTime()); err != nil {
                        http.Error(w, fmt.Sprintf("SQL rewrite: %s", 
err.Error()), http.StatusInternalServerError)
                        return
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/rqlite-9.3.11/store/store.go 
new/rqlite-9.3.14/store/store.go
--- old/rqlite-9.3.11/store/store.go    2026-01-07 05:16:04.000000000 +0100
+++ new/rqlite-9.3.14/store/store.go    2026-01-09 08:01:54.000000000 +0100
@@ -138,6 +138,7 @@
        raftLogCacheSize          = 512
        trailingScale             = 1.25
        observerChanLen           = 50
+       maxFailedSnapshotsInRow   = 5
 
        baseVacuumTimeKey   = "rqlite_base_vacuum"
        lastVacuumTimeKey   = "rqlite_last_vacuum"
@@ -344,9 +345,10 @@
        snapshotWClose chan struct{}
        snapshotWDone  chan struct{}
 
-       // Snapshotting synchronization
-       snapshotSync *rsync.SyncChannels
-       snapshotCAS  *rsync.CheckAndSet
+       // Snapshotting synchronization and and management
+       snapshotSync            *rsync.SyncChannels
+       snapshotCAS             *rsync.CheckAndSet
+       numFailedSnapshotsInRow int
 
        // Latest log entry index actually reflected by the FSM. Due to Raft 
code
        // these values are not updated automatically after a Snapshot-restore.
@@ -2533,22 +2535,11 @@
        var walTmpFD *os.File
        if fullNeeded {
                chkStartTime := time.Now()
-               meta, err := s.db.Checkpoint(sql.CheckpointTruncate)
-               if err != nil {
+               if err := s.checkpointWAL(); err != nil {
                        stats.Add(numFullCheckpointFailed, 1)
-                       return nil, fmt.Errorf("snapshot can't complete due to 
FULL Snapshot checkpoint error (will retry): %s",
+                       return nil, fmt.Errorf("full snapshot can't complete 
due to WAL checkpoint error (will retry): %s",
                                err.Error())
                }
-               if !meta.Success() {
-                       if meta.Moved < meta.Pages {
-                               stats.Add(numWALCheckpointIncomplete, 1)
-                               return nil, fmt.Errorf("snapshot can't complete 
due to FULL Snapshot checkpoint incomplete (will retry): %s)",
-                                       meta.String())
-                       }
-                       s.logger.Printf("full Snapshot checkpoint moved %d/%d 
pages, but did not truncate WAL, forcing truncate",
-                               meta.Moved, meta.Pages)
-                       s.mustTruncateCheckpoint()
-               }
                
stats.Get(snapshotCreateChkTruncateDuration).(*expvar.Int).Set(time.Since(chkStartTime).Milliseconds())
                dbFD, err := os.Open(s.db.Path())
                if err != nil {
@@ -2605,22 +2596,11 @@
                                return nil, err
                        }
                        chkTStartTime := time.Now()
-                       meta, err := s.db.Checkpoint(sql.CheckpointTruncate)
-                       if err != nil {
+                       if err := s.checkpointWAL(); err != nil {
                                stats.Add(numWALCheckpointTruncateFailed, 1)
-                               return nil, fmt.Errorf("snapshot can't complete 
due to WAL checkpoint error (will retry): %s",
+                               return nil, fmt.Errorf("incremental snapshot 
can't complete due to WAL checkpoint error (will retry): %s",
                                        err.Error())
                        }
-                       if !meta.Success() {
-                               if meta.Moved < meta.Pages {
-                                       stats.Add(numWALCheckpointIncomplete, 1)
-                                       return nil, fmt.Errorf("snapshot can't 
complete due to Snapshot checkpoint incomplete (will retry %s)",
-                                               meta.String())
-                               }
-                               s.logger.Printf("incremental Snapshot 
checkpoint moved %d/%d pages, but did not truncate WAL, forcing truncate",
-                                       meta.Moved, meta.Pages)
-                               s.mustTruncateCheckpoint()
-                       }
                        
stats.Get(snapshotCreateChkTruncateDuration).(*expvar.Int).Set(time.Since(chkTStartTime).Milliseconds())
                        
stats.Get(snapshotPrecompactWALSize).(*expvar.Int).Set(walSzPre)
                        stats.Get(snapshotWALSize).(*expvar.Int).Set(walSzPost)
@@ -2923,6 +2903,46 @@
        return closeCh, doneCh
 }
 
+// checkpointWAL performs a checkpoint of the WAL, truncating it. If it 
returns an error
+// the checkpoint operation can be retried at the caller's discretion. If this 
function
+// encounters an error such that the checkpoint must be retried, it will 
automatically do
+// that until it is successful (or a timeout fires).
+//
+// This function also implements the policy that if a certain number of 
checkpoint attempts
+// fail in a row, it will loop until is successful.
+func (s *Store) checkpointWAL() (retErr error) {
+       defer func() {
+               if retErr != nil {
+                       s.numFailedSnapshotsInRow++
+                       if s.numFailedSnapshotsInRow == maxFailedSnapshotsInRow 
{
+                               s.logger.Printf("too many failed snapshots in a 
row (%d), forcing WAL checkpoint truncate",
+                                       s.numFailedSnapshotsInRow)
+                               s.mustTruncateCheckpoint()
+                               s.numFailedSnapshotsInRow = 0
+                               retErr = nil
+                       }
+               } else {
+                       s.numFailedSnapshotsInRow = 0
+               }
+       }()
+
+       meta, err := s.db.Checkpoint(sql.CheckpointTruncate)
+       if err != nil {
+               return err
+       }
+       if !meta.Success() {
+               if meta.Pages == meta.Moved {
+                       s.logger.Printf("checkpoint moved %d/%d pages, but did 
not truncate WAL, forcing truncate",
+                               meta.Moved, meta.Pages)
+                       s.mustTruncateCheckpoint()
+                       return nil
+               }
+               stats.Add(numWALCheckpointIncomplete, 1)
+               return fmt.Errorf("checkpoint incomplete: %s", meta.String())
+       }
+       return nil
+}
+
 // mustTruncateCheckpoint truncates the checkpointed WAL, retrying until 
successful or
 // timing out.
 //
@@ -2932,8 +2952,8 @@
 // We do this by blocking all readers (writes are already blocked). This 
handling is due to
 // research into SQLite and not seen as of yet.
 //
-// Finally, we could still panic here if we timeout trying to truncate. This 
could happen if
-// a reader external to rqlite just won't let go.
+// Finally, we could still timeout here while trying to truncate. This could 
happen if a
+// reader external to rqlite just won't let go.
 func (s *Store) mustTruncateCheckpoint() {
        startT := time.Now()
        defer func() {
@@ -2954,7 +2974,10 @@
                                return
                        }
                case <-time.After(mustWALCheckpointTimeout):
-                       s.logger.Fatal("timed out trying to truncate 
checkpointed WAL - aborting")
+                       msg := fmt.Sprintf("timed out trying to truncate 
checkpoint WAL after %s,"+
+                               " probably due to external long-running read - 
aborting",
+                               mustWALCheckpointTimeout)
+                       s.logger.Fatal(msg)
                }
        }
 }

++++++ vendor.tar.xz ++++++

Reply via email to