syntropy 0.35.0 → 0.36.0
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/CHANGELOG.md +5 -0
- data/TODO.md +0 -2
- data/cmd/new/template/Gemfile +1 -1
- data/cmd/new/template/app/_lib/storage.rb +13 -0
- data/examples/blog/app/_lib/posts.rb +3 -3
- data/examples/blog/app/_lib/storage.rb +13 -0
- data/lib/syntropy/module_loader.rb +1 -1
- data/lib/syntropy/{db → storage}/connection_pool.rb +2 -1
- data/lib/syntropy/storage/kv_store.rb +68 -0
- data/lib/syntropy/storage/prepared_query.rb +36 -0
- data/lib/syntropy/{db → storage}/schema.rb +1 -1
- data/lib/syntropy/{db → storage}/store.rb +1 -1
- data/lib/syntropy/storage.rb +6 -0
- data/lib/syntropy/test.rb +3 -1
- data/lib/syntropy/version.rb +1 -1
- data/lib/syntropy.rb +2 -4
- data/test/{test_db_connection_pool.rb → test_connection_pool.rb} +4 -4
- data/test/test_kv_store.rb +84 -0
- data/test/{test_db_schema.rb → test_schema.rb} +5 -5
- data/test/{test_db_store.rb → test_store.rb} +3 -3
- metadata +13 -32
- data/cmd/new/template/app/_lib/database.rb +0 -13
- data/cmd/new/template_old/site/.gitignore +0 -57
- data/cmd/new/template_old/site/Dockerfile +0 -32
- data/cmd/new/template_old/site/Gemfile +0 -3
- data/cmd/new/template_old/site/README.md +0 -0
- data/cmd/new/template_old/site/bin/console +0 -0
- data/cmd/new/template_old/site/bin/restart +0 -0
- data/cmd/new/template_old/site/bin/server +0 -0
- data/cmd/new/template_old/site/bin/start +0 -0
- data/cmd/new/template_old/site/bin/stop +0 -0
- data/cmd/new/template_old/site/docker-compose.yml +0 -51
- data/cmd/new/template_old/site/proxy/Dockerfile +0 -5
- data/cmd/new/template_old/site/proxy/etc/Caddyfile +0 -7
- data/cmd/new/template_old/site/proxy/etc/tls_auto +0 -2
- data/cmd/new/template_old/site/proxy/etc/tls_cloudflare +0 -4
- data/cmd/new/template_old/site/proxy/etc/tls_custom +0 -1
- data/cmd/new/template_old/site/proxy/etc/tls_selfsigned +0 -1
- data/cmd/new/template_old/site/site/_layout/default.rb +0 -11
- data/cmd/new/template_old/site/site/about.md +0 -6
- data/cmd/new/template_old/site/site/articles/cage.rb +0 -29
- data/cmd/new/template_old/site/site/articles/index.rb +0 -3
- data/cmd/new/template_old/site/site/assets/css/style.css +0 -40
- data/cmd/new/template_old/site/site/assets/img/syntropy.png +0 -0
- data/cmd/new/template_old/site/site/index.rb +0 -15
- data/examples/blog/app/_lib/database.rb +0 -13
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f92ed1375642f12fb92654d872bfde1d07c7ad74be97507af3c1616390b6ce14
|
|
4
|
+
data.tar.gz: 5072d514bc07149f1d26bc900bcc9379970ebbbaf1b88eaa23933189fb684b37
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f77aed02801a7b1c10f67a5ed7fbac9196580bd482c19ca660c81beaf5f2adcba86047635e35f9750d003538b12401962888193c058fbc3023ae88eae9038506
|
|
7
|
+
data.tar.gz: f923ab3aa4e535d5a85a563acf7f97534639ca1ed3d02e2c2b94d9cecef57e06cefc3a72a1ca782d0118b012189298bc3c743b017c0ee2d06be8bbf55d03dc89
|
data/CHANGELOG.md
CHANGED
data/TODO.md
CHANGED
data/cmd/new/template/Gemfile
CHANGED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export self
|
|
2
|
+
|
|
3
|
+
def connection_pool
|
|
4
|
+
@connection_pool ||= Storage::ConnectionPool.new(@machine, @env[:config][:storage][:path], 4)
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def schema
|
|
8
|
+
Storage::Schema.new(module_loader: @module_loader, schema_root: '_schema')
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def migrate!
|
|
12
|
+
schema.apply(connection_pool)
|
|
13
|
+
end
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
Storage = import '/_lib/storage'
|
|
2
2
|
|
|
3
|
-
class PostStore < Syntropy::
|
|
3
|
+
class PostStore < Syntropy::Storage::Store
|
|
4
4
|
# @return [Integer] post id
|
|
5
5
|
def create(title, body)
|
|
6
6
|
query_single_value <<~SQL, title:, body:
|
|
@@ -46,4 +46,4 @@ class PostStore < Syntropy::DB::Store
|
|
|
46
46
|
end
|
|
47
47
|
end
|
|
48
48
|
|
|
49
|
-
export PostStore.new(
|
|
49
|
+
export PostStore.new(Storage.connection_pool)
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export self
|
|
2
|
+
|
|
3
|
+
def connection_pool
|
|
4
|
+
@connection_pool ||= Storage::ConnectionPool.new(@machine, @env[:config][:storage][:path], 4)
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def schema
|
|
8
|
+
Storage::Schema.new(module_loader: @module_loader, schema_root: '_schema')
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def migrate!
|
|
12
|
+
schema.apply(connection_pool)
|
|
13
|
+
end
|
|
@@ -200,7 +200,7 @@ module Syntropy
|
|
|
200
200
|
m
|
|
201
201
|
rescue SyntaxError => e
|
|
202
202
|
env[:logger]&.error(message: "Error while loading module at #{fn}", error: e)
|
|
203
|
-
STDERR.puts("\n#{e.message}")
|
|
203
|
+
STDERR.puts("\n#{e.message}") if !Syntropy.test_mode
|
|
204
204
|
|
|
205
205
|
if (m = e.message.match(/^(.+)\: syntax/))
|
|
206
206
|
location = m[1]
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'syntropy/storage/store'
|
|
4
|
+
|
|
5
|
+
module Syntropy
|
|
6
|
+
module Storage
|
|
7
|
+
# The KVStore class implements an SQLite-backed key-value store
|
|
8
|
+
class KVStore < Store
|
|
9
|
+
attr_reader :q_get, :q_set
|
|
10
|
+
|
|
11
|
+
def self.apply_schema(db, table_name)
|
|
12
|
+
db.execute <<~SQL
|
|
13
|
+
create table if not exists #{table_name} (key text primary key, value, expires float);
|
|
14
|
+
create index if not exists idx_#{table_name}_expires on #{table_name} (expires) where expires is not null;
|
|
15
|
+
SQL
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def initialize(connection_pool, table_name)
|
|
19
|
+
super(connection_pool)
|
|
20
|
+
@table_name = table_name
|
|
21
|
+
|
|
22
|
+
setup_queries
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def get(db, key)
|
|
26
|
+
db[@q_get].bind(key).next
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def set(db, key, value)
|
|
30
|
+
db[@q_set].execute(key, value)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def setex(db, key, value, ttl)
|
|
34
|
+
db[@q_setex].execute(key, value, ttl ? Time.now.to_f + ttl : nil)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def sweep(db)
|
|
38
|
+
db[@q_sweep].execute(Time.now.to_f)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
private
|
|
42
|
+
|
|
43
|
+
def setup_queries
|
|
44
|
+
@q_get = Storage.prepare_splat <<~SQL
|
|
45
|
+
select value from #{@table_name}
|
|
46
|
+
where key = ?
|
|
47
|
+
SQL
|
|
48
|
+
|
|
49
|
+
@q_set = Storage.prepare <<~SQL
|
|
50
|
+
insert into #{@table_name} (key, value)
|
|
51
|
+
values($1, $2)
|
|
52
|
+
on conflict (key) do update set value = $2, expires = null
|
|
53
|
+
SQL
|
|
54
|
+
|
|
55
|
+
@q_setex = Storage.prepare <<~SQL
|
|
56
|
+
insert into #{@table_name} (key, value, expires)
|
|
57
|
+
values($1, $2, $3)
|
|
58
|
+
on conflict (key) do update set value = $2, expires = $3
|
|
59
|
+
SQL
|
|
60
|
+
|
|
61
|
+
@q_sweep = Storage.prepare <<~SQL
|
|
62
|
+
delete from #{@table_name}
|
|
63
|
+
where expires < ?
|
|
64
|
+
SQL
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'extralite'
|
|
4
|
+
|
|
5
|
+
module Syntropy
|
|
6
|
+
module Storage
|
|
7
|
+
class << self
|
|
8
|
+
def prepare(sql)
|
|
9
|
+
PreparedQuery.new(sql)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def prepare_splat(sql)
|
|
13
|
+
PreparedQuery.new(sql, :prepare_splat)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Represents information about a prepared query
|
|
18
|
+
class PreparedQuery
|
|
19
|
+
attr_reader :sql, :mode
|
|
20
|
+
|
|
21
|
+
def initialize(sql, mode = :prepare)
|
|
22
|
+
@sql = sql
|
|
23
|
+
@mode = mode
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Extensions for Extralite::Database
|
|
28
|
+
module ExtraliteDatabaseExtensions
|
|
29
|
+
def [](pq)
|
|
30
|
+
(@prepared_queries ||= {})[pq] ||= send(pq.mode, pq.sql)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
::Extralite::Database.include(ExtraliteDatabaseExtensions)
|
|
35
|
+
end
|
|
36
|
+
end
|
data/lib/syntropy/test.rb
CHANGED
|
@@ -118,7 +118,7 @@ module Syntropy
|
|
|
118
118
|
)
|
|
119
119
|
@test_harness = Syntropy::TestHarness.new(@app)
|
|
120
120
|
|
|
121
|
-
@db = load_module('/_lib/
|
|
121
|
+
@db = load_module('/_lib/storage', raise_on_missing: false)
|
|
122
122
|
@db&.migrate!
|
|
123
123
|
end
|
|
124
124
|
|
|
@@ -241,3 +241,5 @@ module Syntropy
|
|
|
241
241
|
|
|
242
242
|
Request.include TestRequestExtensions
|
|
243
243
|
end
|
|
244
|
+
|
|
245
|
+
Syntropy.test_mode = true
|
data/lib/syntropy/version.rb
CHANGED
data/lib/syntropy.rb
CHANGED
|
@@ -9,9 +9,7 @@ require 'syntropy/logger'
|
|
|
9
9
|
require 'syntropy/http'
|
|
10
10
|
require 'syntropy/mime_types'
|
|
11
11
|
require 'syntropy/app'
|
|
12
|
-
require 'syntropy/
|
|
13
|
-
require 'syntropy/db/schema'
|
|
14
|
-
require 'syntropy/db/store'
|
|
12
|
+
require 'syntropy/storage'
|
|
15
13
|
require 'syntropy/errors'
|
|
16
14
|
require 'syntropy/markdown'
|
|
17
15
|
require 'syntropy/module_loader'
|
|
@@ -29,7 +27,7 @@ module Syntropy
|
|
|
29
27
|
extend Utilities
|
|
30
28
|
|
|
31
29
|
class << self
|
|
32
|
-
attr_accessor :machine, :dev_mode
|
|
30
|
+
attr_accessor :machine, :dev_mode, :test_mode
|
|
33
31
|
|
|
34
32
|
# Runs the given block on a separate thread. Use this method for running
|
|
35
33
|
# code that is not fiber-aware (i.e. does not use UringMachine).
|
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
require_relative 'helper'
|
|
4
4
|
|
|
5
|
-
class
|
|
5
|
+
class ConnectionPoolTest < Minitest::Test
|
|
6
6
|
def setup
|
|
7
7
|
@machine = UM.new
|
|
8
8
|
@fn = "/tmp/#{rand(100000)}.db"
|
|
9
|
-
@cp = Syntropy::
|
|
9
|
+
@cp = Syntropy::Storage::ConnectionPool.new(@machine, @fn, 4)
|
|
10
10
|
|
|
11
11
|
FileUtils.rm(@fn) rescue nil
|
|
12
12
|
@standalone_db = Extralite::Database.new(@fn)
|
|
@@ -19,7 +19,7 @@ class DBConnectionPoolTest < Minitest::Test
|
|
|
19
19
|
@cp.close
|
|
20
20
|
end
|
|
21
21
|
|
|
22
|
-
def
|
|
22
|
+
def test_connection_pool_with_db
|
|
23
23
|
assert_equal 0, @cp.count
|
|
24
24
|
|
|
25
25
|
@cp.with_db do |db|
|
|
@@ -74,7 +74,7 @@ class DBConnectionPoolTest < Minitest::Test
|
|
|
74
74
|
assert_equal 4, @cp.count
|
|
75
75
|
end
|
|
76
76
|
|
|
77
|
-
def
|
|
77
|
+
def test_connection_pool_with_db_reentrant
|
|
78
78
|
dbs = @cp.with_db do |db1|
|
|
79
79
|
@cp.with_db do |db2|
|
|
80
80
|
[db1, db2]
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'helper'
|
|
4
|
+
require 'syntropy/storage/kv_store'
|
|
5
|
+
|
|
6
|
+
class KVStoreTest < Minitest::Test
|
|
7
|
+
def setup
|
|
8
|
+
@machine = UM.new
|
|
9
|
+
@fn = "/tmp/#{rand(100000)}.db"
|
|
10
|
+
FileUtils.rm(@fn) rescue nil
|
|
11
|
+
@cp = Syntropy::Storage::ConnectionPool.new(@machine, @fn, 4)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def teardown
|
|
15
|
+
@cp.close
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def test_connection_pool_prepare
|
|
19
|
+
pq = Syntropy::Storage.prepare('select ? as a, 42 as b')
|
|
20
|
+
assert_kind_of Syntropy::Storage::PreparedQuery, pq
|
|
21
|
+
assert_equal 'select ? as a, 42 as b', pq.sql
|
|
22
|
+
assert_equal :prepare, pq.mode
|
|
23
|
+
|
|
24
|
+
assert_kind_of Extralite::Query, @cp.with_db { it[pq] }
|
|
25
|
+
assert_equal [{ a: 'foo', b: 42 }], @cp.with_db { it[pq].bind('foo').to_a }
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def test_connection_pool_prepare_splat
|
|
29
|
+
pq = Syntropy::Storage.prepare_splat('select ?')
|
|
30
|
+
assert_kind_of Syntropy::Storage::PreparedQuery, pq
|
|
31
|
+
assert_equal 'select ?', pq.sql
|
|
32
|
+
assert_equal :prepare_splat, pq.mode
|
|
33
|
+
|
|
34
|
+
assert_kind_of Extralite::Query, @cp.with_db { it[pq] }
|
|
35
|
+
assert_equal ['foo'], @cp.with_db { it[pq].bind('foo').to_a }
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def test_kv_store_apply_schema
|
|
39
|
+
assert_respond_to Syntropy::Storage::KVStore, :apply_schema
|
|
40
|
+
|
|
41
|
+
assert_raises(Extralite::SQLError) { @cp.query('select * from kv') }
|
|
42
|
+
Syntropy::Storage::KVStore.apply_schema(@cp, 'kv')
|
|
43
|
+
assert_equal [], @cp.query('select * from kv')
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def test_kv_store_get_set
|
|
47
|
+
Syntropy::Storage::KVStore.apply_schema(@cp, 'kv')
|
|
48
|
+
kv_store = Syntropy::Storage::KVStore.new(@cp, 'kv')
|
|
49
|
+
|
|
50
|
+
@cp.with_db do |db|
|
|
51
|
+
assert_nil kv_store.get(db, 'foo')
|
|
52
|
+
assert_nil kv_store.get(db, 'bar')
|
|
53
|
+
|
|
54
|
+
kv_store.set(db, 'foo', '123')
|
|
55
|
+
|
|
56
|
+
assert_equal '123', kv_store.get(db, 'foo')
|
|
57
|
+
assert_nil kv_store.get(db, 'bar')
|
|
58
|
+
|
|
59
|
+
kv_store.set(db, 'bar', '456')
|
|
60
|
+
assert_equal '123', kv_store.get(db, 'foo')
|
|
61
|
+
assert_equal '456', kv_store.get(db, 'bar')
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def test_kv_store_setex_sweep
|
|
66
|
+
Syntropy::Storage::KVStore.apply_schema(@cp, 'kv')
|
|
67
|
+
kv_store = Syntropy::Storage::KVStore.new(@cp, 'kv')
|
|
68
|
+
|
|
69
|
+
@cp.with_db do |db|
|
|
70
|
+
kv_store.set(db, 'foo', '123')
|
|
71
|
+
kv_store.setex(db, 'bar', '456', 0.05)
|
|
72
|
+
assert_equal 0, kv_store.sweep(db)
|
|
73
|
+
|
|
74
|
+
assert_equal '123', kv_store.get(db, 'foo')
|
|
75
|
+
assert_equal '456', kv_store.get(db, 'bar')
|
|
76
|
+
|
|
77
|
+
sleep 0.1
|
|
78
|
+
assert_equal 1, kv_store.sweep(db)
|
|
79
|
+
|
|
80
|
+
assert_equal '123', kv_store.get(db, 'foo')
|
|
81
|
+
assert_nil kv_store.get(db, 'bar')
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
require_relative 'helper'
|
|
4
4
|
|
|
5
|
-
class
|
|
5
|
+
class SchemaTest < Minitest::Test
|
|
6
6
|
def setup
|
|
7
7
|
@machine = UM.new
|
|
8
8
|
@fn = "/tmp/#{rand(100000)}.db"
|
|
9
9
|
FileUtils.rm(@fn) rescue nil
|
|
10
|
-
@cp = Syntropy::
|
|
10
|
+
@cp = Syntropy::Storage::ConnectionPool.new(@machine, @fn, 4)
|
|
11
11
|
end
|
|
12
12
|
|
|
13
13
|
def teardown
|
|
@@ -15,7 +15,7 @@ class DBSchemaTest < Minitest::Test
|
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
def test_db_schema_initial
|
|
18
|
-
schema = Syntropy::
|
|
18
|
+
schema = Syntropy::Storage::Schema.new do
|
|
19
19
|
initial do |db|
|
|
20
20
|
db.execute <<~SQL
|
|
21
21
|
create table posts (
|
|
@@ -35,7 +35,7 @@ class DBSchemaTest < Minitest::Test
|
|
|
35
35
|
end
|
|
36
36
|
|
|
37
37
|
def test_db_schema_version_blocks
|
|
38
|
-
schema = Syntropy::
|
|
38
|
+
schema = Syntropy::Storage::Schema.new do
|
|
39
39
|
initial do |db|
|
|
40
40
|
db.execute <<~SQL
|
|
41
41
|
create table posts (
|
|
@@ -79,7 +79,7 @@ class DBSchemaTest < Minitest::Test
|
|
|
79
79
|
module_loader = Syntropy::ModuleLoader.new({
|
|
80
80
|
app_root: File.join(__dir__, 'fixtures/schema')
|
|
81
81
|
})
|
|
82
|
-
schema = Syntropy::
|
|
82
|
+
schema = Syntropy::Storage::Schema.new(module_loader:, schema_root: '/')
|
|
83
83
|
|
|
84
84
|
assert_nil schema.current_version(@cp)
|
|
85
85
|
schema.apply(@cp)
|
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
require_relative 'helper'
|
|
4
4
|
|
|
5
|
-
class
|
|
5
|
+
class StoreTest < Minitest::Test
|
|
6
6
|
def setup
|
|
7
7
|
@machine = UM.new
|
|
8
8
|
@fn = "/tmp/#{rand(100000)}.db"
|
|
9
9
|
FileUtils.rm(@fn) rescue nil
|
|
10
|
-
@cp = Syntropy::
|
|
10
|
+
@cp = Syntropy::Storage::ConnectionPool.new(@machine, @fn, 4)
|
|
11
11
|
end
|
|
12
12
|
|
|
13
13
|
def teardown
|
|
@@ -15,7 +15,7 @@ class DBStoreTest < Minitest::Test
|
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
def test_db_store
|
|
18
|
-
store = Syntropy::
|
|
18
|
+
store = Syntropy::Storage::Store.new(@cp)
|
|
19
19
|
|
|
20
20
|
assert_equal [{a: 42}], store.query("select ? as a", 42)
|
|
21
21
|
assert_equal({a: 42}, store.query_single_row("select ? as a", 42))
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: syntropy
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.36.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Sharon Rosner
|
|
@@ -176,7 +176,7 @@ files:
|
|
|
176
176
|
- cmd/new/template/Gemfile
|
|
177
177
|
- cmd/new/template/README.md
|
|
178
178
|
- cmd/new/template/app/_layout/default.rb
|
|
179
|
-
- cmd/new/template/app/_lib/
|
|
179
|
+
- cmd/new/template/app/_lib/storage.rb
|
|
180
180
|
- cmd/new/template/app/_schema/2026-01-01-initial.rb
|
|
181
181
|
- cmd/new/template/app/assets/style.css
|
|
182
182
|
- cmd/new/template/app/index.rb
|
|
@@ -186,29 +186,6 @@ files:
|
|
|
186
186
|
- cmd/new/template/config/test.rb
|
|
187
187
|
- cmd/new/template/docker-compose.yml
|
|
188
188
|
- cmd/new/template/test/test_app.rb
|
|
189
|
-
- cmd/new/template_old/site/.gitignore
|
|
190
|
-
- cmd/new/template_old/site/Dockerfile
|
|
191
|
-
- cmd/new/template_old/site/Gemfile
|
|
192
|
-
- cmd/new/template_old/site/README.md
|
|
193
|
-
- cmd/new/template_old/site/bin/console
|
|
194
|
-
- cmd/new/template_old/site/bin/restart
|
|
195
|
-
- cmd/new/template_old/site/bin/server
|
|
196
|
-
- cmd/new/template_old/site/bin/start
|
|
197
|
-
- cmd/new/template_old/site/bin/stop
|
|
198
|
-
- cmd/new/template_old/site/docker-compose.yml
|
|
199
|
-
- cmd/new/template_old/site/proxy/Dockerfile
|
|
200
|
-
- cmd/new/template_old/site/proxy/etc/Caddyfile
|
|
201
|
-
- cmd/new/template_old/site/proxy/etc/tls_auto
|
|
202
|
-
- cmd/new/template_old/site/proxy/etc/tls_cloudflare
|
|
203
|
-
- cmd/new/template_old/site/proxy/etc/tls_custom
|
|
204
|
-
- cmd/new/template_old/site/proxy/etc/tls_selfsigned
|
|
205
|
-
- cmd/new/template_old/site/site/_layout/default.rb
|
|
206
|
-
- cmd/new/template_old/site/site/about.md
|
|
207
|
-
- cmd/new/template_old/site/site/articles/cage.rb
|
|
208
|
-
- cmd/new/template_old/site/site/articles/index.rb
|
|
209
|
-
- cmd/new/template_old/site/site/assets/css/style.css
|
|
210
|
-
- cmd/new/template_old/site/site/assets/img/syntropy.png
|
|
211
|
-
- cmd/new/template_old/site/site/index.rb
|
|
212
189
|
- cmd/serve.rb
|
|
213
190
|
- cmd/test.rb
|
|
214
191
|
- docker-compose.yml
|
|
@@ -222,8 +199,8 @@ files:
|
|
|
222
199
|
- examples/basic/templates.rb
|
|
223
200
|
- examples/blog/.gitignore
|
|
224
201
|
- examples/blog/app/_layout/default.rb
|
|
225
|
-
- examples/blog/app/_lib/database.rb
|
|
226
202
|
- examples/blog/app/_lib/posts.rb
|
|
203
|
+
- examples/blog/app/_lib/storage.rb
|
|
227
204
|
- examples/blog/app/_schema/2026-01-01-initial.rb
|
|
228
205
|
- examples/blog/app/assets/style.css
|
|
229
206
|
- examples/blog/app/index.rb
|
|
@@ -262,9 +239,6 @@ files:
|
|
|
262
239
|
- lib/syntropy/applets/builtin/json_api.js
|
|
263
240
|
- lib/syntropy/applets/builtin/ping.rb
|
|
264
241
|
- lib/syntropy/applets/builtin/req.rb
|
|
265
|
-
- lib/syntropy/db/connection_pool.rb
|
|
266
|
-
- lib/syntropy/db/schema.rb
|
|
267
|
-
- lib/syntropy/db/store.rb
|
|
268
242
|
- lib/syntropy/dev_mode.rb
|
|
269
243
|
- lib/syntropy/errors.rb
|
|
270
244
|
- lib/syntropy/http.rb
|
|
@@ -288,6 +262,12 @@ files:
|
|
|
288
262
|
- lib/syntropy/routing_tree.rb
|
|
289
263
|
- lib/syntropy/session.rb
|
|
290
264
|
- lib/syntropy/side_run.rb
|
|
265
|
+
- lib/syntropy/storage.rb
|
|
266
|
+
- lib/syntropy/storage/connection_pool.rb
|
|
267
|
+
- lib/syntropy/storage/kv_store.rb
|
|
268
|
+
- lib/syntropy/storage/prepared_query.rb
|
|
269
|
+
- lib/syntropy/storage/schema.rb
|
|
270
|
+
- lib/syntropy/storage/store.rb
|
|
291
271
|
- lib/syntropy/test.rb
|
|
292
272
|
- lib/syntropy/utils.rb
|
|
293
273
|
- lib/syntropy/version.rb
|
|
@@ -340,23 +320,24 @@ files:
|
|
|
340
320
|
- test/run.rb
|
|
341
321
|
- test/test_app.rb
|
|
342
322
|
- test/test_caching.rb
|
|
343
|
-
- test/
|
|
344
|
-
- test/test_db_schema.rb
|
|
345
|
-
- test/test_db_store.rb
|
|
323
|
+
- test/test_connection_pool.rb
|
|
346
324
|
- test/test_errors.rb
|
|
347
325
|
- test/test_http_client.rb
|
|
348
326
|
- test/test_http_client_connection.rb
|
|
349
327
|
- test/test_http_protocol.rb
|
|
350
328
|
- test/test_http_server_connection.rb
|
|
351
329
|
- test/test_json_api.rb
|
|
330
|
+
- test/test_kv_store.rb
|
|
352
331
|
- test/test_mock_adapter.rb
|
|
353
332
|
- test/test_module_loader.rb
|
|
354
333
|
- test/test_request.rb
|
|
355
334
|
- test/test_request_session.rb
|
|
356
335
|
- test/test_response.rb
|
|
357
336
|
- test/test_routing_tree.rb
|
|
337
|
+
- test/test_schema.rb
|
|
358
338
|
- test/test_server.rb
|
|
359
339
|
- test/test_side_run.rb
|
|
340
|
+
- test/test_store.rb
|
|
360
341
|
- test/test_test.rb
|
|
361
342
|
homepage: https://github.com/digital-fabric/syntropy
|
|
362
343
|
licenses:
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
export self
|
|
2
|
-
|
|
3
|
-
def connection_pool
|
|
4
|
-
@connection_pool ||= DB::ConnectionPool.new(@machine, @env[:config][:storage][:path], 4)
|
|
5
|
-
end
|
|
6
|
-
|
|
7
|
-
def schema
|
|
8
|
-
DB::Schema.new(module_loader: @module_loader, schema_root: '_schema')
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
def migrate!
|
|
12
|
-
schema.apply(connection_pool)
|
|
13
|
-
end
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
*.gem
|
|
2
|
-
*.rbc
|
|
3
|
-
/.config
|
|
4
|
-
/coverage/
|
|
5
|
-
/InstalledFiles
|
|
6
|
-
/pkg/
|
|
7
|
-
/spec/reports/
|
|
8
|
-
/spec/examples.txt
|
|
9
|
-
/test/tmp/
|
|
10
|
-
/test/version_tmp/
|
|
11
|
-
/tmp/
|
|
12
|
-
|
|
13
|
-
# Used by dotenv library to load environment variables.
|
|
14
|
-
# .env
|
|
15
|
-
|
|
16
|
-
# Ignore Byebug command history file.
|
|
17
|
-
.byebug_history
|
|
18
|
-
|
|
19
|
-
## Specific to RubyMotion:
|
|
20
|
-
.dat*
|
|
21
|
-
.repl_history
|
|
22
|
-
build/
|
|
23
|
-
*.bridgesupport
|
|
24
|
-
build-iPhoneOS/
|
|
25
|
-
build-iPhoneSimulator/
|
|
26
|
-
|
|
27
|
-
## Specific to RubyMotion (use of CocoaPods):
|
|
28
|
-
#
|
|
29
|
-
# We recommend against adding the Pods directory to your .gitignore. However
|
|
30
|
-
# you should judge for yourself, the pros and cons are mentioned at:
|
|
31
|
-
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
|
|
32
|
-
#
|
|
33
|
-
# vendor/Pods/
|
|
34
|
-
|
|
35
|
-
## Documentation cache and generated files:
|
|
36
|
-
/.yardoc/
|
|
37
|
-
/_yardoc/
|
|
38
|
-
/doc/
|
|
39
|
-
/rdoc/
|
|
40
|
-
|
|
41
|
-
## Environment normalization:
|
|
42
|
-
/.bundle/
|
|
43
|
-
/vendor/bundle
|
|
44
|
-
/lib/bundler/man/
|
|
45
|
-
|
|
46
|
-
# for a library or gem, you might want to ignore these files since the code is
|
|
47
|
-
# intended to run in multiple environments; otherwise, check them in:
|
|
48
|
-
# Gemfile.lock
|
|
49
|
-
# .ruby-version
|
|
50
|
-
# .ruby-gemset
|
|
51
|
-
|
|
52
|
-
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
|
|
53
|
-
.rvmrc
|
|
54
|
-
|
|
55
|
-
# Used by RuboCop. Remote config files pulled in from inherit_from directive.
|
|
56
|
-
# .rubocop-https?--*
|
|
57
|
-
log
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
ARG RUBY_BASE_IMAGE=ruby:3.4.1-alpine
|
|
2
|
-
ARG GEM_CACHE_IMAGE=${RUBY_BASE_IMAGE}
|
|
3
|
-
|
|
4
|
-
# base image
|
|
5
|
-
FROM ${RUBY_BASE_IMAGE} AS base
|
|
6
|
-
RUN apk add --update sqlite-dev openssl-dev tzdata bash curl zip git
|
|
7
|
-
RUN apk add --update build-base
|
|
8
|
-
RUN gem install bundler:2.6.9
|
|
9
|
-
|
|
10
|
-
# gem cache
|
|
11
|
-
FROM ${GEM_CACHE_IMAGE} AS gem-cache
|
|
12
|
-
RUN mkdir -p /usr/local/bundle
|
|
13
|
-
|
|
14
|
-
FROM base AS gems
|
|
15
|
-
COPY --from=gem-cache /usr/local/bundle /usr/local/bundle
|
|
16
|
-
COPY Gemfile Gemfile.lock ./
|
|
17
|
-
RUN bundle install --jobs=4 --retry=5
|
|
18
|
-
|
|
19
|
-
# Final backend image
|
|
20
|
-
FROM base AS deploy
|
|
21
|
-
|
|
22
|
-
RUN adduser -D app
|
|
23
|
-
RUN chown app:app /home/app
|
|
24
|
-
WORKDIR /home/app
|
|
25
|
-
USER app
|
|
26
|
-
|
|
27
|
-
RUN mkdir -p /tmp
|
|
28
|
-
COPY --from=gems --chown=app:app /usr/local/bundle /usr/local/bundle
|
|
29
|
-
|
|
30
|
-
EXPOSE 1234
|
|
31
|
-
|
|
32
|
-
CMD ["bundle", "exec", "syntropy", "."]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
services:
|
|
2
|
-
backend:
|
|
3
|
-
build: .
|
|
4
|
-
privileged: true
|
|
5
|
-
restart: always
|
|
6
|
-
ports:
|
|
7
|
-
- 127.0.0.1:1234:1234
|
|
8
|
-
# expose:
|
|
9
|
-
# - 1234
|
|
10
|
-
volumes:
|
|
11
|
-
- .:/home/app
|
|
12
|
-
deploy:
|
|
13
|
-
# replicas: 1
|
|
14
|
-
resources:
|
|
15
|
-
limits:
|
|
16
|
-
memory: 500M
|
|
17
|
-
# restart: unless-stopped
|
|
18
|
-
logging:
|
|
19
|
-
driver: "json-file"
|
|
20
|
-
options:
|
|
21
|
-
max-size: "1M"
|
|
22
|
-
max-file: "10"
|
|
23
|
-
|
|
24
|
-
# healthcheck:
|
|
25
|
-
# test: "curl 'http://localhost:1234/?q=ping'"
|
|
26
|
-
# interval: "30s"
|
|
27
|
-
# timeout: "3s"
|
|
28
|
-
# start_period: "5s"
|
|
29
|
-
# retries: 3
|
|
30
|
-
|
|
31
|
-
proxy:
|
|
32
|
-
depends_on:
|
|
33
|
-
- backend
|
|
34
|
-
build:
|
|
35
|
-
context: ./proxy
|
|
36
|
-
dockerfile: Dockerfile
|
|
37
|
-
restart: always
|
|
38
|
-
volumes:
|
|
39
|
-
- ./proxy/etc/Caddyfile:/etc/caddy/Caddyfile
|
|
40
|
-
ports:
|
|
41
|
-
- "80:80"
|
|
42
|
-
- "443:443"
|
|
43
|
-
- "443:443/udp"
|
|
44
|
-
# env_file:
|
|
45
|
-
# - ./conf/caddy.env
|
|
46
|
-
# - ./conf/caddy_sensitive.env
|
|
47
|
-
logging:
|
|
48
|
-
driver: "json-file"
|
|
49
|
-
options:
|
|
50
|
-
max-size: "1M"
|
|
51
|
-
max-file: "10"
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
tls {$TLS_CUSTOM_CERT} {$TLS_CUSTOM_KEY}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
tls internal
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
layout = import('_layout/default')
|
|
2
|
-
|
|
3
|
-
poem = [
|
|
4
|
-
" in ten\xA0", 'M', 'inutes',
|
|
5
|
-
' ', 'C', 'ome back: you will',
|
|
6
|
-
'have taught me chi', 'N', 'ese',
|
|
7
|
-
' (s', 'A', 'tie).',
|
|
8
|
-
' shall I ret', 'U', 'rn the favor?',
|
|
9
|
-
' ', 'G', 'ive you',
|
|
10
|
-
' ot', 'H', 'er lessons',
|
|
11
|
-
' (', 'T', 'ing!)?',
|
|
12
|
-
' ', 'O', 'r would you prefer',
|
|
13
|
-
' sile', 'N', 'ce?',
|
|
14
|
-
]
|
|
15
|
-
|
|
16
|
-
export Papercraft.apply(layout) {
|
|
17
|
-
article(class: 'mesostic') {
|
|
18
|
-
h2 'For William McN. who studied with Ezra Pound'
|
|
19
|
-
|
|
20
|
-
content {
|
|
21
|
-
span(_for: poem) { text it }
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
author {
|
|
25
|
-
span "-\xA0"
|
|
26
|
-
a 'John cage', href: 'https://en.wikipedia.org/wiki/John_Cage'
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
}
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
body {
|
|
2
|
-
font-family: sans-serif;
|
|
3
|
-
}
|
|
4
|
-
|
|
5
|
-
article.mesostic {
|
|
6
|
-
width: 600px;
|
|
7
|
-
margin: 2em auto;
|
|
8
|
-
font-size: 1.4em;
|
|
9
|
-
|
|
10
|
-
* {
|
|
11
|
-
font-family: monospace;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
h2 {
|
|
15
|
-
text-align: center;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
content {
|
|
19
|
-
display: grid;
|
|
20
|
-
margin: 2em 0;
|
|
21
|
-
grid-template-columns: 1fr auto 1fr;
|
|
22
|
-
|
|
23
|
-
span {
|
|
24
|
-
display: inline-block;
|
|
25
|
-
}
|
|
26
|
-
span:nth-child(3n + 1) {
|
|
27
|
-
text-align: right;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
span:nth-child(3n + 2) {
|
|
31
|
-
text-align: center;
|
|
32
|
-
font-weight: bold;
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
author {
|
|
37
|
-
display: block;
|
|
38
|
-
text-align: right;
|
|
39
|
-
}
|
|
40
|
-
}
|
|
File without changes
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
layout = import('_layout/default')
|
|
2
|
-
|
|
3
|
-
export Papercraft.apply(layout) {
|
|
4
|
-
h1 'Hello from Syntropy'
|
|
5
|
-
p {
|
|
6
|
-
span "Here's an "
|
|
7
|
-
a 'about', href: 'about'
|
|
8
|
-
span ' page.'
|
|
9
|
-
}
|
|
10
|
-
p {
|
|
11
|
-
span "Here's an "
|
|
12
|
-
a 'article', href: 'articles/cage'
|
|
13
|
-
span ' page.'
|
|
14
|
-
}
|
|
15
|
-
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
export self
|
|
2
|
-
|
|
3
|
-
def connection_pool
|
|
4
|
-
@connection_pool ||= DB::ConnectionPool.new(@machine, @env[:config][:storage][:path], 4)
|
|
5
|
-
end
|
|
6
|
-
|
|
7
|
-
def schema
|
|
8
|
-
DB::Schema.new(module_loader: @module_loader, schema_root: '_schema')
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
def migrate!
|
|
12
|
-
schema.apply(connection_pool)
|
|
13
|
-
end
|