virgodb 0.1.4-x86_64-linux-gnu → 0.3.0-x86_64-linux-gnu
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/virgodb/table.rb +68 -4
- data/lib/virgodb/version.rb +1 -1
- data/lib/virgodb/virgodb_ruby.so +0 -0
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6141e1a5628b4293f7d63bd3143fe20bcbff6f697df38fc67c1da4c2669369ab
|
|
4
|
+
data.tar.gz: 7814e9e3a10ba0ce4e5126e492d38410637aa818d21abb4352b6f038fc9b4139
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: '0468833ba6f07aed2d56ea13ca5d158a523fb64486ec4fa5259c969200f9c4e991fb96a545ad26a78c8531460855c59dcbcc0904be5a8d43f558dd2bb4f27255'
|
|
7
|
+
data.tar.gz: 475c654f9a604b83c05b0036c4cdffb478c339b05fb794a9cef445b5244584394cef90289bbb57cdc8f7c65a8918fb7a8111e545d9a790c6b375eca454929a47
|
data/lib/virgodb/table.rb
CHANGED
|
@@ -11,6 +11,19 @@ module Virgodb
|
|
|
11
11
|
# just failing the first write attempt. Mutex-guarded so concurrent
|
|
12
12
|
# callers in one process can't race to double-initialize.
|
|
13
13
|
#
|
|
14
|
+
# The SAME mutex also serializes every actual write_row/tombstone/flush!
|
|
15
|
+
# call, not just lazy Writer init -- the underlying Rust Writer wraps a
|
|
16
|
+
# plain RefCell, explicitly documented "not thread-safe by design," so
|
|
17
|
+
# two Ruby threads calling in concurrently would double-borrow it. This
|
|
18
|
+
# is safe today even without a Ruby-level lock, PURELY because none of
|
|
19
|
+
# those three Rust entry points release the GVL (crates/virgodb_ruby/
|
|
20
|
+
# src/writer.rs, tombstone.rs) -- MRI's GVL already fully serializes them.
|
|
21
|
+
# That's an implicit invariant a future perf change could silently break
|
|
22
|
+
# (the read path already got its own GVL-release fix once, see the root
|
|
23
|
+
# README's "Known issues" -- the write path getting the same treatment
|
|
24
|
+
# someday isn't a hypothetical). Locking explicitly here means this
|
|
25
|
+
# class's correctness no longer depends on that invariant holding.
|
|
26
|
+
#
|
|
14
27
|
# This is the boilerplate every host app embedding virgodb needs around
|
|
15
28
|
# the raw Writer/start_maintenance/query FFI -- written once here instead
|
|
16
29
|
# of once per host app. Deliberately does NOT rescue write failures: a
|
|
@@ -35,8 +48,18 @@ module Virgodb
|
|
|
35
48
|
|
|
36
49
|
attr_reader :manifest_path
|
|
37
50
|
|
|
51
|
+
# `writer` is called BEFORE entering `@mutex.synchronize` here (and in
|
|
52
|
+
# `tombstone`/`flush!` below), never from inside it -- `writer`'s own
|
|
53
|
+
# lazy-init path takes the SAME mutex when it actually needs to build
|
|
54
|
+
# one, and Ruby's Mutex is not reentrant (a thread re-locking a mutex
|
|
55
|
+
# it already holds raises ThreadError immediately, it doesn't queue).
|
|
56
|
+
# Safe regardless of ordering: `@writer` is assigned at most once and
|
|
57
|
+
# never reassigned afterward, so the reference `writer` returns stays
|
|
58
|
+
# valid and correct for the rest of this object's lifetime no matter
|
|
59
|
+
# what happens between fetching it and entering the lock below.
|
|
38
60
|
def write_row(**attrs)
|
|
39
|
-
writer
|
|
61
|
+
w = writer
|
|
62
|
+
@mutex.synchronize { w.write_row(**attrs) }
|
|
40
63
|
end
|
|
41
64
|
|
|
42
65
|
# `tombstone` alone doesn't touch the Writer -- calling `writer` first
|
|
@@ -45,19 +68,60 @@ module Virgodb
|
|
|
45
68
|
# recorded for it to eventually act on.
|
|
46
69
|
def tombstone(column:, value:)
|
|
47
70
|
writer
|
|
48
|
-
Virgodb.tombstone(@manifest_path, @sql_table_name, column.to_s, value.to_s)
|
|
71
|
+
@mutex.synchronize { Virgodb.tombstone(@manifest_path, @sql_table_name, column.to_s, value.to_s) }
|
|
49
72
|
end
|
|
50
73
|
|
|
51
74
|
# Returns parsed JSON rows (Array of String-keyed Hash). `sql` must
|
|
52
75
|
# refer to the table by its real SQL name (the `sql_table_name` this
|
|
53
76
|
# instance was built with), not any shorthand a caller's own registry
|
|
54
|
-
# might use for it.
|
|
77
|
+
# might use for it. Not mutex-guarded -- a read never touches the
|
|
78
|
+
# Writer's RefCell state at all (Virgodb.query is a separate, already
|
|
79
|
+
# GVL-released, independently-safe-for-concurrency FFI entry point).
|
|
55
80
|
def query(sql, partition_keys: nil)
|
|
56
81
|
JSON.parse(Virgodb.query(@manifest_path, @sql_table_name, sql, partition_keys))
|
|
57
82
|
end
|
|
58
83
|
|
|
59
84
|
def flush!
|
|
60
|
-
writer
|
|
85
|
+
w = writer
|
|
86
|
+
@mutex.synchronize { w.flush! }
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# This table's current maintenance status (a String-keyed Hash with
|
|
90
|
+
# "holder"/"lease_expires_at"/"last_attempt_at"/"last_success_at"/
|
|
91
|
+
# "last_error"), or nil if maintenance has never even attempted a lease
|
|
92
|
+
# claim yet (e.g. this Table hasn't done its first write, so
|
|
93
|
+
# start_maintenance was never called -- see `ensure_maintenance_started`).
|
|
94
|
+
# A real answer to "is this table's background maintenance actually
|
|
95
|
+
# working," not just "is the thread alive" -- meant to be polled by a
|
|
96
|
+
# host app's own health check, not by this class itself. Not
|
|
97
|
+
# mutex-guarded, same reasoning as `query` above: a read never touches
|
|
98
|
+
# the Writer's RefCell state.
|
|
99
|
+
def maintenance_health
|
|
100
|
+
json = Virgodb.maintenance_health(@manifest_path, @sql_table_name)
|
|
101
|
+
json && JSON.parse(json)
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# Claims this table's maintenance lease as `holder` for the next
|
|
105
|
+
# `lease_duration_secs` seconds, locking out the real maintenance
|
|
106
|
+
# thread (its own claim attempts fail against an unexpired lease the
|
|
107
|
+
# same way two maintenance threads would contend) -- meant for a
|
|
108
|
+
# caller like a backup job that needs a window where compaction/vacuum
|
|
109
|
+
# won't rewrite or delete this table's data directory. Returns `false`
|
|
110
|
+
# (not an error) if someone else's lease is still active; callers
|
|
111
|
+
# should retry rather than treat that as failure. Doesn't call `writer`
|
|
112
|
+
# first (unlike `tombstone` above) -- claiming a lease has nothing to
|
|
113
|
+
# do with this table's Writer, and a caller like a backup job may never
|
|
114
|
+
# otherwise touch this table's Writer in this process at all. Not
|
|
115
|
+
# mutex-guarded, same reasoning as `query`/`maintenance_health` above.
|
|
116
|
+
def claim_maintenance_lease(holder:, lease_duration_secs:)
|
|
117
|
+
Virgodb.claim_maintenance_lease(@manifest_path, @sql_table_name, holder.to_s, lease_duration_secs)
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
# Releases a lease claimed via `claim_maintenance_lease` above, so the
|
|
121
|
+
# real maintenance thread can resume on its next poll rather than
|
|
122
|
+
# waiting out the full lease duration.
|
|
123
|
+
def release_maintenance_lease(holder:)
|
|
124
|
+
Virgodb.release_maintenance_lease(@manifest_path, @sql_table_name, holder.to_s)
|
|
61
125
|
end
|
|
62
126
|
|
|
63
127
|
private
|
data/lib/virgodb/version.rb
CHANGED
data/lib/virgodb/virgodb_ruby.so
CHANGED
|
Binary file
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: virgodb
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.3.0
|
|
5
5
|
platform: x86_64-linux-gnu
|
|
6
6
|
authors:
|
|
7
7
|
- virgodb
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-09-02 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
13
|
description: |
|
|
14
14
|
Embeds virgodb (an OLAP engine backed by Parquet + DataFusion) directly into a Ruby process
|