qwe 0.0.0 → 0.0.2
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/DOCS.md +7 -4
- data/Gemfile.lock +3 -5
- data/README.md +23 -3
- data/exe/qwe +4 -26
- data/lib/qwe/attribute.rb +7 -48
- data/lib/qwe/console.rb +66 -0
- data/lib/qwe/db/commits_file.rb +26 -14
- data/lib/qwe/db/record.rb +1 -1
- data/lib/qwe/db/worker.rb +1 -1
- data/lib/qwe/proxy/array.rb +29 -0
- data/lib/qwe/proxy/hash.rb +28 -0
- data/lib/qwe/proxy.rb +43 -0
- data/lib/qwe/version.rb +1 -1
- data/lib/qwe.rb +1 -0
- data/qwe.gemspec +1 -1
- metadata +10 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9163afb748f542c3cee0749fa5cb182100c2c46c5eb52c7834dd6a9e9928e569
|
4
|
+
data.tar.gz: f36a49f10487cae9d6c6caeb5774946355d072e832d4139f6e3f74af8b65b8dc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c11193ca71612d9433848ec7217da3d9b795be3f73b70fc1f0ce6a01254bd908d3a6472c33aff7d1d8f7e72b30ad91492b7be02261d02bac1a3c2391369ae6d1
|
7
|
+
data.tar.gz: e2147f520f70ec10510236d22e62a48b28eb5b1bb63b9db759d0dce62a8d491e63e90c0d452e83d5aca9251ef8fe0f63c3679f4ce682eea074600d2f3e34e665
|
data/DOCS.md
CHANGED
@@ -5,7 +5,7 @@
|
|
5
5
|
Gem provides `qwe` executable, which starts the server by default. See `qwe -h` for details.
|
6
6
|
|
7
7
|
`-r` parameter is required for entrypoint to load your classes.
|
8
|
-
|
8
|
+
In rails it's reasonable to have `config/qwe.rb` for that purpose:
|
9
9
|
```ruby
|
10
10
|
APP_PATH = File.realpath("../")
|
11
11
|
|
@@ -46,6 +46,8 @@ Configuration of server started from puma is done with `config/qwe.yml`. Valid c
|
|
46
46
|
are last variants of cli argument names. For example, detach timeout can be set with
|
47
47
|
`-s`, `--detach` and `--detach_timeout` cli options, or `detach_timeout` config key.
|
48
48
|
|
49
|
+
`--watch` is not available in puma plugin.
|
50
|
+
|
49
51
|
## Production example
|
50
52
|
|
51
53
|
config/puma.rb
|
@@ -219,7 +221,7 @@ multi-line, so it isn't equal to commits count.
|
|
219
221
|
- `commit(str)` - write string to commits file. Attributes do that for you.
|
220
222
|
- `object_at(line)` - returns historic object state, or wayback, by evaluating commits until `line` in context of initial object state.
|
221
223
|
- `fork(line)` - same as object_at, but creates a new record. Returns newly created `Qwe::DB::Record`.
|
222
|
-
- `archive!` - compress commits file with `zst`.
|
224
|
+
- `archive!` - compress commits file with `zst`. If commit is written into archived record, file will get unpacked with a warning.
|
223
225
|
- `dir` - path to the record directory in filesystem
|
224
226
|
- `dump` - `Marshal.dump(object)`
|
225
227
|
|
@@ -266,7 +268,8 @@ attribute :zxc, init: -> { Time.now }
|
|
266
268
|
attribute :qwe, min: 10
|
267
269
|
attribute :asd, max: 20
|
268
270
|
```
|
269
|
-
- `array` - `bool` - initializes attribute to `Qwe::
|
271
|
+
- `array` - `bool` - initializes attribute to `Qwe::Proxy::Array`, which is like array, but commits changes, see [limitations](#Limitations) on why it matters.
|
272
|
+
- `hash` - `bool` - same as array, but for hashes. Attribute type is `Qwe::Proxy::Hash`.
|
270
273
|
- `enum` - `Array` or any object responding to `include?` - raise on write if value is not included in provided enum.
|
271
274
|
```ruby
|
272
275
|
attribute :weather, enum: [:hot, :cold, :normal]
|
@@ -433,7 +436,7 @@ As we expect, resulting `a.str` value would be "qxe". However, `sub!` modifies s
|
|
433
436
|
a.str = a.str.sub "w", "x"
|
434
437
|
```
|
435
438
|
|
436
|
-
For strings this is somewhat fine, but for large arrays things get worse. For arrays there is `Qwe::
|
439
|
+
For strings this is somewhat fine, but for large arrays things get worse. For arrays there is `Qwe::Proxy::Array` class, which extends `Array` class and commits changes.
|
437
440
|
|
438
441
|
So the rule here is **don't use in-place modifications on attributes**, and if you need these - extend desired class and write committing logic. Be sure to benchmark results - sometimes replacing object entirely would be faster than doing complex checks.
|
439
442
|
|
data/Gemfile.lock
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
qwe (0.0.
|
4
|
+
qwe (0.0.1)
|
5
5
|
drb (~> 2.2.1)
|
6
|
-
ruby
|
6
|
+
zstd-ruby (~> 1.5)
|
7
7
|
|
8
8
|
GEM
|
9
9
|
remote: https://rubygems.org/
|
10
10
|
specs:
|
11
|
-
adsp (1.0.10)
|
12
11
|
ast (2.4.2)
|
13
12
|
cgi (0.4.1)
|
14
13
|
drb (2.2.1)
|
@@ -51,8 +50,6 @@ GEM
|
|
51
50
|
rubocop (>= 1.48.1, < 2.0)
|
52
51
|
rubocop-ast (>= 1.30.0, < 2.0)
|
53
52
|
ruby-progressbar (1.13.0)
|
54
|
-
ruby-zstds (1.3.1)
|
55
|
-
adsp (~> 1.0)
|
56
53
|
standard (1.35.1)
|
57
54
|
language_server-protocol (~> 3.17.0.2)
|
58
55
|
lint_roller (~> 1.0)
|
@@ -68,6 +65,7 @@ GEM
|
|
68
65
|
standardrb (1.0.1)
|
69
66
|
standard
|
70
67
|
unicode-display_width (2.5.0)
|
68
|
+
zstd-ruby (1.5.6.6)
|
71
69
|
|
72
70
|
PLATFORMS
|
73
71
|
x86_64-linux
|
data/README.md
CHANGED
@@ -1,10 +1,28 @@
|
|
1
1
|
# Qwe - pure ruby framework for stuff
|
2
2
|
|
3
|
-
|
4
|
-
|
3
|
+
It might be useful if you have:
|
4
|
+
- Extra high loads
|
5
|
+
- Extensive interaction
|
6
|
+
- Complexity in fitting into database
|
7
|
+
|
8
|
+
Qwe is built upon [DRb](https://docs.ruby-lang.org/en/3.3/DRb.html), which provides a way to directly access ruby objects from different processes, thus avoiding latency, JSON or XML conversions, and disk I/O limits.
|
9
|
+
|
10
|
+
Qwe manages:
|
11
|
+
- Serving and accessing objects over DRb
|
12
|
+
- Persisting them on disk
|
13
|
+
- Loading them back into RAM upon access
|
14
|
+
- Tracing every change
|
5
15
|
|
6
16
|
[Full Documentation](DOCS.md)
|
7
17
|
|
18
|
+
[Multiplayer paint example](https://gitlab.com/goose3228/qwe-paint) - Qwe is fast enough to process mouse events on server side.
|
19
|
+
|
20
|
+
## Installation
|
21
|
+
|
22
|
+
Qwe requires native [zstd](https://github.com/facebook/zstd) support.
|
23
|
+
|
24
|
+
Otherwise it's regular `bundle add qwe` or `gem install qwe`
|
25
|
+
|
8
26
|
## Features
|
9
27
|
|
10
28
|
### Zero-config startup
|
@@ -24,7 +42,7 @@ The hash is now accessible from any ruby process with `Qwe::DB[]`,
|
|
24
42
|
considering you know that id.
|
25
43
|
|
26
44
|
```ruby
|
27
|
-
Qwe::DB[id][:
|
45
|
+
Qwe::DB[id][:one_two_three] = 123
|
28
46
|
```
|
29
47
|
|
30
48
|
After a period of inactivity, or manually if configured,
|
@@ -127,6 +145,8 @@ by running independent Qwe servers.
|
|
127
145
|
DRb does not provide any access control, and opens separate port for each object it serves.
|
128
146
|
It is safe to run Qwe in docker container or other isolated network, and unsafe to run on virtual or physical device with all ports open.
|
129
147
|
|
148
|
+
In web applications Qwe may be accessed though websockets without providing direct access to ruby methods.
|
149
|
+
|
130
150
|
See [DRb docs](https://docs.ruby-lang.org/en/3.3/DRb.html#module-DRb-label-Security) for a more detailed explanation.
|
131
151
|
|
132
152
|
## License
|
data/exe/qwe
CHANGED
@@ -39,7 +39,7 @@ opt_parser = OptionParser.new do |parser|
|
|
39
39
|
args[:threads] = a.to_i
|
40
40
|
end
|
41
41
|
|
42
|
-
parser.on("--gc=SECONDS", "--gc_interval=SECONDS", "Call garbage collector (GC.start) every x seconds. Off by default") do |a|
|
42
|
+
parser.on("--gc=SECONDS", "--gc_interval=SECONDS", "Call garbage collector (GC.start) every x seconds. Off by default. Ruby can ignore garbage collection at 100% CPU load, and --gc forces ruby to still do that.") do |a|
|
43
43
|
args[:gc_interval] = a.to_i
|
44
44
|
end
|
45
45
|
|
@@ -66,7 +66,7 @@ if args[:watch]
|
|
66
66
|
begin
|
67
67
|
require "listen"
|
68
68
|
rescue LoadError
|
69
|
-
puts "
|
69
|
+
puts "'listen' gem is required to use -w/--watch option"
|
70
70
|
exit 1
|
71
71
|
end
|
72
72
|
pid = spawn_server(args)
|
@@ -86,30 +86,8 @@ if args[:watch]
|
|
86
86
|
end
|
87
87
|
sleep
|
88
88
|
elsif args[:interactive]
|
89
|
-
|
90
|
-
|
91
|
-
Qwe::DB.connect("druby://localhost:#{args[:port]}") if args[:port]
|
92
|
-
|
93
|
-
if args[:interactive] > 0
|
94
|
-
obj = Qwe::DB[args[:interactive]]
|
95
|
-
puts "\e[0;32mQwe interactive prompt\e[0m, record \e[1;32m##{args[:interactive]}\e[0m, class \e[1;36m#{obj.record.obj_eval("self.class.to_s")}\e[0m"
|
96
|
-
else
|
97
|
-
obj = Qwe::DB.server.pick_worker
|
98
|
-
puts "\e[0;32mQwe interactive prompt\e[0m, worker \e[1;36m#{obj.uri}\e[0m, require #{obj.requirements}"
|
99
|
-
|
100
|
-
require obj.requirements
|
101
|
-
end
|
102
|
-
|
103
|
-
(obj.instance_exec { binding }).instance_exec do
|
104
|
-
irb(show_code: false)
|
105
|
-
rescue
|
106
|
-
# Older irb versions always print source code around call point
|
107
|
-
IRB.setup(source_location[0], argv: [])
|
108
|
-
workspace = IRB::WorkSpace.new(self)
|
109
|
-
binding_irb = IRB::Irb.new(workspace)
|
110
|
-
binding_irb.context.irb_path = File.expand_path(source_location[0])
|
111
|
-
binding_irb.run(IRB.conf)
|
112
|
-
end
|
89
|
+
require_relative "../lib/qwe/console"
|
90
|
+
Qwe::Console.start(args[:interactive], args[:port])
|
113
91
|
elsif args[:create]
|
114
92
|
Qwe::DB.connect("druby://localhost:#{args[:port]}") if args[:port]
|
115
93
|
puts Qwe::DB.create(args[:create].to_sym)
|
data/lib/qwe/attribute.rb
CHANGED
@@ -116,7 +116,7 @@ module Qwe
|
|
116
116
|
end
|
117
117
|
|
118
118
|
add(:default) do
|
119
|
-
reader.stage "self.#{name} = " + init_or_default_stage(:default) + "
|
119
|
+
reader.stage "self.#{name} = " + init_or_default_stage(:default) + " if @#{name}.nil?"
|
120
120
|
end
|
121
121
|
|
122
122
|
add(:convert) do
|
@@ -134,60 +134,19 @@ module Qwe
|
|
134
134
|
end
|
135
135
|
|
136
136
|
add(:array) do
|
137
|
-
writer.stage "value = Qwe::
|
137
|
+
writer.stage "value = Qwe::Proxy::Array.from_array(self, :#{name}, value)"
|
138
138
|
klass.init.stage("self.#{name} = []") unless init
|
139
139
|
end
|
140
140
|
|
141
|
+
add(:hash) do
|
142
|
+
writer.stage "value = Qwe::Proxy::Hash.from_hash(self, :#{name}, value)"
|
143
|
+
klass.init.stage("self.#{name} = {}") unless init
|
144
|
+
end
|
145
|
+
|
141
146
|
add(:enum) do
|
142
147
|
raise "#{klass}.#{name} - enum #{enum} doesn't respond to include?" unless enum.respond_to?(:include?)
|
143
148
|
klass.class_variable_set(:"@@#{name}_enum", enum)
|
144
149
|
writer.stage "raise \"Enum - unknown value \#{self}.#{name} = \#{value}\" unless @@#{name}_enum.include?(value)"
|
145
150
|
end
|
146
|
-
|
147
|
-
class ArrayProxy < Array
|
148
|
-
attr_accessor :__qwe_thing
|
149
|
-
attr_accessor :__qwe_name
|
150
|
-
|
151
|
-
include DRb::DRbUndumped
|
152
|
-
|
153
|
-
undef _dump
|
154
|
-
|
155
|
-
def __qwe_commit(m, *a, **k)
|
156
|
-
__qwe_thing&.root&.record&.commit("#{__qwe_thing.to_rb}.#{__qwe_name}.method(:#{m}).super_method.call(*#{a.to_rb}, **#{k.to_rb})\n")
|
157
|
-
end
|
158
|
-
|
159
|
-
TRANSACTION_METHODS = [:<<, :[]=, :clear, :compact!, :concat, :delete_at, :flatten!, :insert, :pop, :push, :replace, :reverse!, :rotate!, :shift, :shuffle!, :slice!, :unshift]
|
160
|
-
REPLACE_METHODS = [:delete, :delete_if, :fill, :filter!, :select!, :keep_if, :map!, :reject!, :sort!, :sort_by!, :uniq!]
|
161
|
-
|
162
|
-
TRANSACTION_METHODS.each do |m|
|
163
|
-
define_method(m) do |*a, **k|
|
164
|
-
__qwe_commit(m, *a, **k)
|
165
|
-
super(*a, **k)
|
166
|
-
end
|
167
|
-
end
|
168
|
-
|
169
|
-
REPLACE_METHODS.each do |m|
|
170
|
-
define_method(m) do |*a, **k, &block|
|
171
|
-
r = super(*a, **k, &block)
|
172
|
-
if block
|
173
|
-
__qwe_thing&.root&.record&.commit "#{__qwe_thing.to_rb}.instance_variable_set(:@#{__qwe_name}, #{to_rb})\n"
|
174
|
-
else
|
175
|
-
__qwe_commit(m, *a, **k)
|
176
|
-
end
|
177
|
-
r
|
178
|
-
end
|
179
|
-
end
|
180
|
-
|
181
|
-
def self.from_array(thing, name, arr = [])
|
182
|
-
a = new(arr)
|
183
|
-
a.__qwe_thing = thing
|
184
|
-
a.__qwe_name = name
|
185
|
-
a
|
186
|
-
end
|
187
|
-
|
188
|
-
def to_rb
|
189
|
-
"Qwe::Attribute::ArrayProxy.from_array(#{__qwe_thing.to_rb}, :#{__qwe_name}, #{super})"
|
190
|
-
end
|
191
|
-
end
|
192
151
|
end
|
193
152
|
end
|
data/lib/qwe/console.rb
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
require "irb"
|
2
|
+
|
3
|
+
module Qwe
|
4
|
+
class Console
|
5
|
+
def self.start(...)
|
6
|
+
new(...).start
|
7
|
+
end
|
8
|
+
|
9
|
+
attr_reader :id, :port
|
10
|
+
|
11
|
+
def initialize(id = 0, port = nil)
|
12
|
+
@id = id.to_i
|
13
|
+
@port = if port
|
14
|
+
port.to_i
|
15
|
+
else
|
16
|
+
Qwe::DB::Server::DEFAULT_PORT
|
17
|
+
end
|
18
|
+
|
19
|
+
Qwe::DB.connect("druby://localhost:#{port}") if port
|
20
|
+
setup
|
21
|
+
end
|
22
|
+
|
23
|
+
def setup
|
24
|
+
if id > 0
|
25
|
+
IRB::WorkSpace.define_method(:evaluate, &record_proc)
|
26
|
+
req = Qwe::DB[id].record.evaluate("Worker.instance.requirements")
|
27
|
+
msg = "\e[1;35mQwe interactive prompt\e[0m, record \e[1;32m##{id}\e[0m"
|
28
|
+
else
|
29
|
+
IRB::WorkSpace.define_method(:evaluate, &worker_proc)
|
30
|
+
req = Qwe::DB.server.pick_worker.requirements
|
31
|
+
msg = "\e[1;35mQwe interactive prompt\e[0m, random worker"
|
32
|
+
end
|
33
|
+
|
34
|
+
puts msg
|
35
|
+
require req if req
|
36
|
+
end
|
37
|
+
|
38
|
+
def to_s
|
39
|
+
"Qwe id=#{id}"
|
40
|
+
end
|
41
|
+
|
42
|
+
def start
|
43
|
+
binding.irb(show_code: false)
|
44
|
+
rescue
|
45
|
+
# Older irb versions always print source code around call point
|
46
|
+
IRB.setup(source_location[0], argv: [])
|
47
|
+
workspace = IRB::WorkSpace.new(self)
|
48
|
+
binding_irb = IRB::Irb.new(workspace)
|
49
|
+
binding_irb.context.irb_path = File.expand_path(source_location[0])
|
50
|
+
binding_irb.run(IRB.conf)
|
51
|
+
end
|
52
|
+
|
53
|
+
def record_proc
|
54
|
+
i = id
|
55
|
+
proc do |statements, *args|
|
56
|
+
Qwe::DB[i].record.evaluate(statements)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def worker_proc
|
61
|
+
proc do |statements, *args|
|
62
|
+
Qwe::DB.server.pick_worker.evaluate(statements)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
data/lib/qwe/db/commits_file.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "
|
3
|
+
require "zstd-ruby"
|
4
4
|
require "fileutils"
|
5
5
|
|
6
6
|
module Qwe::DB
|
@@ -12,17 +12,23 @@ module Qwe::DB
|
|
12
12
|
def initialize(dir)
|
13
13
|
@path = File.join(dir, "commits")
|
14
14
|
@archive_path = File.join(dir, "commits.zst")
|
15
|
-
|
16
|
-
|
17
|
-
|
15
|
+
open
|
16
|
+
end
|
17
|
+
|
18
|
+
def open
|
19
|
+
return if @file && !@file.closed? || File.exist?(@archive_path)
|
20
|
+
@file = File.open(@path, "a+")
|
18
21
|
end
|
19
22
|
|
20
23
|
def write(str)
|
21
|
-
|
24
|
+
if !file
|
22
25
|
log "Write #{str} to archived commits file #{path}, unpacking"
|
23
|
-
|
24
|
-
FileUtils.rm_f(archive_path)
|
26
|
+
data = read_archive
|
25
27
|
@file = File.open(@path, "a+")
|
28
|
+
@file.write(data)
|
29
|
+
FileUtils.rm_f(archive_path)
|
30
|
+
elsif file.closed?
|
31
|
+
open
|
26
32
|
end
|
27
33
|
file.write(str)
|
28
34
|
rescue => e
|
@@ -31,7 +37,7 @@ module Qwe::DB
|
|
31
37
|
end
|
32
38
|
|
33
39
|
def read(line = nil)
|
34
|
-
if file
|
40
|
+
if file && !file.closed?
|
35
41
|
file.flush
|
36
42
|
file.rewind
|
37
43
|
if line
|
@@ -41,10 +47,12 @@ module Qwe::DB
|
|
41
47
|
file.read
|
42
48
|
end
|
43
49
|
else
|
44
|
-
cs =
|
45
|
-
|
46
|
-
|
50
|
+
cs = if File.exist?(archive_path)
|
51
|
+
read_archive
|
52
|
+
else
|
53
|
+
File.read(path)
|
47
54
|
end
|
55
|
+
|
48
56
|
if line
|
49
57
|
cs.lines[0, line].join("")
|
50
58
|
else
|
@@ -53,9 +61,13 @@ module Qwe::DB
|
|
53
61
|
end
|
54
62
|
end
|
55
63
|
|
64
|
+
def read_archive
|
65
|
+
Zstd.decompress(File.binread(archive_path)).force_encoding("UTF-8")
|
66
|
+
end
|
67
|
+
|
56
68
|
def archive!
|
57
|
-
|
58
|
-
|
69
|
+
File.binwrite(archive_path, Zstd.compress(read))
|
70
|
+
close
|
59
71
|
FileUtils.rm_f(path)
|
60
72
|
@file = nil
|
61
73
|
end
|
@@ -65,7 +77,7 @@ module Qwe::DB
|
|
65
77
|
end
|
66
78
|
|
67
79
|
def close
|
68
|
-
file&.close
|
80
|
+
file&.close unless file&.closed?
|
69
81
|
end
|
70
82
|
end
|
71
83
|
end
|
data/lib/qwe/db/record.rb
CHANGED
data/lib/qwe/db/worker.rb
CHANGED
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Qwe::Proxy::Array < Array
|
4
|
+
Qwe::Proxy.make self
|
5
|
+
|
6
|
+
Qwe::Proxy.transaction self,
|
7
|
+
:<<, :[]=, :clear, :compact!, :concat, :delete_at, :flatten!,
|
8
|
+
:insert, :pop, :push, :replace, :reverse!, :rotate!, :shift,
|
9
|
+
:shuffle!, :slice!, :unshift
|
10
|
+
|
11
|
+
Qwe::Proxy.block self,
|
12
|
+
:delete, :delete_if, :fill, :filter!, :select!, :keep_if,
|
13
|
+
:map!, :reject!, :sort!, :sort_by!, :uniq!
|
14
|
+
|
15
|
+
def self.from_array(thing, name, arr = [])
|
16
|
+
if arr.is_a?(Qwe::Proxy::Array)
|
17
|
+
arr
|
18
|
+
else
|
19
|
+
a = new(arr)
|
20
|
+
a.__qwe_thing = thing
|
21
|
+
a.__qwe_name = name
|
22
|
+
a
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def to_rb
|
27
|
+
"Qwe::Proxy::Array.from_array(#{__qwe_thing.to_rb}, :#{__qwe_name}, #{super})"
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Qwe::Proxy::Hash < Hash
|
4
|
+
Qwe::Proxy.make self
|
5
|
+
|
6
|
+
Qwe::Proxy.transaction self,
|
7
|
+
:[]=, :store, :clear, :compact!, :default=, :rehash, :replace, :shift
|
8
|
+
|
9
|
+
Qwe::Proxy.block self,
|
10
|
+
:delete, :delete_if, :filter!, :select!, :keep_if, :merge!,
|
11
|
+
:reject!, :transform_keys!, :transform_values!
|
12
|
+
|
13
|
+
def self.from_hash(thing, name, hash = {})
|
14
|
+
if hash.is_a?(Qwe::Proxy::Hash)
|
15
|
+
hash
|
16
|
+
else
|
17
|
+
h = new
|
18
|
+
h.replace(hash)
|
19
|
+
h.__qwe_thing = thing
|
20
|
+
h.__qwe_name = name
|
21
|
+
h
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def to_rb
|
26
|
+
"Qwe::Proxy::Hash.from_hash(#{__qwe_thing.to_rb}, :#{__qwe_name}, #{super})"
|
27
|
+
end
|
28
|
+
end
|
data/lib/qwe/proxy.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
module Qwe
|
2
|
+
module Proxy
|
3
|
+
def self.make(klass)
|
4
|
+
klass.module_exec do
|
5
|
+
attr_accessor :__qwe_thing, :__qwe_name
|
6
|
+
|
7
|
+
include DRb::DRbUndumped
|
8
|
+
|
9
|
+
undef _dump
|
10
|
+
|
11
|
+
def __qwe_commit(m, *a, **k)
|
12
|
+
__qwe_thing&.root&.record&.commit("#{__qwe_thing.to_rb}.#{__qwe_name}.method(:#{m}).super_method.call(*#{a.to_rb}, **#{k.to_rb})\n")
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.transaction(klass, *methods)
|
18
|
+
methods.each do |m|
|
19
|
+
klass.define_method(m) do |*a, **k|
|
20
|
+
__qwe_commit(m, *a, **k)
|
21
|
+
super(*a, **k)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.block(klass, *methods)
|
27
|
+
methods.each do |m|
|
28
|
+
klass.define_method(m) do |*a, **k, &block|
|
29
|
+
r = super(*a, **k, &block)
|
30
|
+
if block
|
31
|
+
__qwe_thing&.root&.record&.commit "#{__qwe_thing.to_rb}.instance_variable_set(:@#{__qwe_name}, #{to_rb})\n"
|
32
|
+
else
|
33
|
+
__qwe_commit(m, *a, **k)
|
34
|
+
end
|
35
|
+
r
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
require_relative "proxy/array"
|
43
|
+
require_relative "proxy/hash"
|
data/lib/qwe/version.rb
CHANGED
data/lib/qwe.rb
CHANGED
data/qwe.gemspec
CHANGED
metadata
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: qwe
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- goose3228
|
8
|
-
autorequire:
|
9
8
|
bindir: exe
|
10
9
|
cert_chain: []
|
11
|
-
date:
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
12
11
|
dependencies:
|
13
12
|
- !ruby/object:Gem::Dependency
|
14
13
|
name: drb
|
@@ -25,19 +24,19 @@ dependencies:
|
|
25
24
|
- !ruby/object:Gem::Version
|
26
25
|
version: 2.2.1
|
27
26
|
- !ruby/object:Gem::Dependency
|
28
|
-
name: ruby
|
27
|
+
name: zstd-ruby
|
29
28
|
requirement: !ruby/object:Gem::Requirement
|
30
29
|
requirements:
|
31
30
|
- - "~>"
|
32
31
|
- !ruby/object:Gem::Version
|
33
|
-
version: '1.
|
32
|
+
version: '1.5'
|
34
33
|
type: :runtime
|
35
34
|
prerelease: false
|
36
35
|
version_requirements: !ruby/object:Gem::Requirement
|
37
36
|
requirements:
|
38
37
|
- - "~>"
|
39
38
|
- !ruby/object:Gem::Version
|
40
|
-
version: '1.
|
39
|
+
version: '1.5'
|
41
40
|
description: Object persistence with DRb access, manual or automatic RAM/disk switch,
|
42
41
|
and transactions as ruby code.
|
43
42
|
email:
|
@@ -58,6 +57,7 @@ files:
|
|
58
57
|
- lib/puma/plugin/qwe.rb
|
59
58
|
- lib/qwe.rb
|
60
59
|
- lib/qwe/attribute.rb
|
60
|
+
- lib/qwe/console.rb
|
61
61
|
- lib/qwe/db.rb
|
62
62
|
- lib/qwe/db/commits_file.rb
|
63
63
|
- lib/qwe/db/record.rb
|
@@ -68,6 +68,9 @@ files:
|
|
68
68
|
- lib/qwe/mixins/process.rb
|
69
69
|
- lib/qwe/mixins/root.rb
|
70
70
|
- lib/qwe/mixins/thing.rb
|
71
|
+
- lib/qwe/proxy.rb
|
72
|
+
- lib/qwe/proxy/array.rb
|
73
|
+
- lib/qwe/proxy/hash.rb
|
71
74
|
- lib/qwe/version.rb
|
72
75
|
- lib/spawn_worker.rb
|
73
76
|
- qwe.gemspec
|
@@ -76,7 +79,6 @@ licenses:
|
|
76
79
|
- MIT
|
77
80
|
metadata:
|
78
81
|
source_code_uri: https://gitlab.com/goose3228/qwe
|
79
|
-
post_install_message:
|
80
82
|
rdoc_options: []
|
81
83
|
require_paths:
|
82
84
|
- lib
|
@@ -91,8 +93,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
91
93
|
- !ruby/object:Gem::Version
|
92
94
|
version: '0'
|
93
95
|
requirements: []
|
94
|
-
rubygems_version: 3.
|
95
|
-
signing_key:
|
96
|
+
rubygems_version: 3.6.9
|
96
97
|
specification_version: 4
|
97
98
|
summary: Framework for in-RAM ruby applications
|
98
99
|
test_files: []
|