funes-rails 0.1.0 → 0.1.1
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/Rakefile +19 -79
- data/app/event_streams/funes/event_stream.rb +16 -8
- data/lib/funes/transactional_projection_failed.rb +17 -0
- data/lib/funes/version.rb +1 -1
- data/lib/templates/docs_index.html.erb +37 -0
- metadata +4 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f475c7d974c06b8ea3700459a6275484b805cab6b5e5ca1822eb33a09bb5b92e
|
|
4
|
+
data.tar.gz: 1ee86eb626084ddf73cfb3921abf3e4a68ab823ad87ff09fd890788ced2063fc
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5bc8898e1014eee4e865c6b1747f640a70f5cbf9336d5356eaa52ef9a557845764ac831ad54d1c5e3e777104c14b44aa5d737be3fb9f12597e5550e4280c4481
|
|
7
|
+
data.tar.gz: bbee4693d75aa24d31133e3738876d6ee0906cbde3fef4eb915d47d0ae74dad5ec91f8787d0eb2293660b9a52d632fa5af44b973a3b22ddcdd685dee7875d9dc
|
data/Rakefile
CHANGED
|
@@ -10,8 +10,11 @@ require "bundler/gem_tasks"
|
|
|
10
10
|
namespace :docs do
|
|
11
11
|
desc "Generate YARD documentation for current version"
|
|
12
12
|
task :generate do
|
|
13
|
-
|
|
14
|
-
version =
|
|
13
|
+
# Allow version override via environment variable (for CI)
|
|
14
|
+
version = ENV["VERSION"] || begin
|
|
15
|
+
require_relative "lib/funes/version"
|
|
16
|
+
Funes::VERSION
|
|
17
|
+
end
|
|
15
18
|
output_dir = "docs/v#{version}"
|
|
16
19
|
|
|
17
20
|
puts "Generating documentation for version #{version}..."
|
|
@@ -31,6 +34,8 @@ namespace :docs do
|
|
|
31
34
|
|
|
32
35
|
desc "Build version selector index page"
|
|
33
36
|
task :build_index do
|
|
37
|
+
require "erb"
|
|
38
|
+
|
|
34
39
|
versions = Dir.glob("docs/v*").map { |d| File.basename(d) }.sort.reverse
|
|
35
40
|
|
|
36
41
|
if versions.empty?
|
|
@@ -39,86 +44,21 @@ namespace :docs do
|
|
|
39
44
|
end
|
|
40
45
|
|
|
41
46
|
latest_version = versions.first
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
<html>
|
|
46
|
-
<head>
|
|
47
|
-
<meta charset="utf-8">
|
|
48
|
-
<title>Funes Documentation</title>
|
|
49
|
-
<link rel="stylesheet" href="css/style.css">
|
|
50
|
-
<style>
|
|
51
|
-
body {
|
|
52
|
-
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
|
53
|
-
max-width: 800px;
|
|
54
|
-
margin: 50px auto;
|
|
55
|
-
padding: 20px;
|
|
56
|
-
line-height: 1.6;
|
|
57
|
-
}
|
|
58
|
-
h1 {
|
|
59
|
-
color: #333;
|
|
60
|
-
border-bottom: 2px solid #0066cc;
|
|
61
|
-
padding-bottom: 10px;
|
|
62
|
-
}
|
|
63
|
-
.version-list {
|
|
64
|
-
list-style: none;
|
|
65
|
-
padding: 0;
|
|
66
|
-
}
|
|
67
|
-
.version-list li {
|
|
68
|
-
margin: 10px 0;
|
|
69
|
-
padding: 15px;
|
|
70
|
-
background: #f5f5f5;
|
|
71
|
-
border-radius: 5px;
|
|
72
|
-
}
|
|
73
|
-
.version-list a {
|
|
74
|
-
text-decoration: none;
|
|
75
|
-
color: #0066cc;
|
|
76
|
-
font-size: 18px;
|
|
77
|
-
font-weight: 500;
|
|
78
|
-
}
|
|
79
|
-
.version-list a:hover {
|
|
80
|
-
text-decoration: underline;
|
|
81
|
-
}
|
|
82
|
-
.latest-badge {
|
|
83
|
-
background: #0066cc;
|
|
84
|
-
color: white;
|
|
85
|
-
padding: 3px 8px;
|
|
86
|
-
border-radius: 3px;
|
|
87
|
-
font-size: 12px;
|
|
88
|
-
margin-left: 10px;
|
|
89
|
-
}
|
|
90
|
-
.description {
|
|
91
|
-
color: #666;
|
|
92
|
-
margin-top: 20px;
|
|
93
|
-
}
|
|
94
|
-
</style>
|
|
95
|
-
</head>
|
|
96
|
-
<body>
|
|
97
|
-
<h1>Funes Documentation</h1>
|
|
98
|
-
<p class="description">Event Sourcing for Rails - Select a version to view documentation</p>
|
|
99
|
-
|
|
100
|
-
<ul class="version-list">
|
|
101
|
-
HTML
|
|
102
|
-
|
|
103
|
-
versions.each do |version|
|
|
104
|
-
is_latest = version == latest_version
|
|
105
|
-
badge = is_latest ? '<span class="latest-badge">latest</span>' : ''
|
|
106
|
-
html += " <li><a href=\"#{version}/index.html\">#{version}#{badge}</a></li>\n"
|
|
107
|
-
end
|
|
108
|
-
|
|
109
|
-
html += <<~HTML
|
|
110
|
-
</ul>
|
|
111
|
-
|
|
112
|
-
<p class="description">
|
|
113
|
-
<a href="https://github.com/funes-org/funes">View on GitHub</a> |
|
|
114
|
-
<a href="https://funes.org/">Official Website</a>
|
|
115
|
-
</p>
|
|
116
|
-
</body>
|
|
117
|
-
</html>
|
|
118
|
-
HTML
|
|
47
|
+
template_path = File.expand_path("lib/templates/docs_index.html.erb", __dir__)
|
|
48
|
+
template = ERB.new(File.read(template_path))
|
|
49
|
+
html = template.result(binding)
|
|
119
50
|
|
|
120
51
|
File.write("docs/index.html", html)
|
|
121
52
|
puts "Version index page created at docs/index.html"
|
|
53
|
+
|
|
54
|
+
# Create CNAME file for GitHub Pages custom domain
|
|
55
|
+
File.write("docs/CNAME", "docs.funes.org\n")
|
|
56
|
+
puts "CNAME file created for docs.funes.org"
|
|
57
|
+
|
|
58
|
+
# Create .nojekyll file to bypass Jekyll processing
|
|
59
|
+
# This is required for YARD's _index.html file to work properly
|
|
60
|
+
File.write("docs/.nojekyll", "")
|
|
61
|
+
puts ".nojekyll file created to bypass Jekyll processing"
|
|
122
62
|
end
|
|
123
63
|
|
|
124
64
|
desc "List all documented versions"
|
|
@@ -165,14 +165,18 @@ module Funes
|
|
|
165
165
|
return new_event unless new_event.valid?
|
|
166
166
|
return new_event if consistency_projection.present? &&
|
|
167
167
|
compute_projection_with_new_event(consistency_projection, new_event).invalid?
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
168
|
+
|
|
169
|
+
ActiveRecord::Base.transaction do
|
|
170
|
+
begin
|
|
171
|
+
@instance_new_events << new_event.persist!(@idx, incremented_version)
|
|
172
|
+
run_transactional_projections
|
|
173
|
+
rescue ActiveRecord::RecordNotUnique, Funes::TransactionalProjectionFailed
|
|
174
|
+
new_event.errors.add(:base, I18n.t("funes.events.racing_condition_on_insert"))
|
|
175
|
+
raise ActiveRecord::Rollback
|
|
176
|
+
end
|
|
172
177
|
end
|
|
173
178
|
|
|
174
|
-
|
|
175
|
-
schedule_async_projections
|
|
179
|
+
schedule_async_projections unless new_event.errors.any?
|
|
176
180
|
|
|
177
181
|
new_event
|
|
178
182
|
end
|
|
@@ -202,8 +206,12 @@ module Funes
|
|
|
202
206
|
|
|
203
207
|
private
|
|
204
208
|
def run_transactional_projections
|
|
205
|
-
|
|
206
|
-
|
|
209
|
+
begin
|
|
210
|
+
transactional_projections.each do |projection_class|
|
|
211
|
+
Funes::PersistProjectionJob.perform_now(@idx, projection_class, last_event_creation_date)
|
|
212
|
+
end
|
|
213
|
+
rescue ActiveRecord::StatementInvalid => e
|
|
214
|
+
raise Funes::TransactionalProjectionFailed, e.message
|
|
207
215
|
end
|
|
208
216
|
end
|
|
209
217
|
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
module Funes
|
|
2
|
+
# Raised when a transactional projection fails due to a database constraint violation.
|
|
3
|
+
#
|
|
4
|
+
# This error wraps database-level errors (like NOT NULL violations, unique constraint
|
|
5
|
+
# violations, etc.) that occur during the persistence of a transactional projection.
|
|
6
|
+
# When this happens, the entire transaction (including the event) is rolled back.
|
|
7
|
+
#
|
|
8
|
+
# @example Handling projection failures
|
|
9
|
+
# stream = OrderEventStream.for("order-123")
|
|
10
|
+
# event = stream.append!(Order::Placed.new(total: 99.99))
|
|
11
|
+
#
|
|
12
|
+
# if event.errors[:base].present?
|
|
13
|
+
# # The projection failed and transaction was rolled back
|
|
14
|
+
# Rails.logger.error "Projection failed: #{event.errors.full_messages}"
|
|
15
|
+
# end
|
|
16
|
+
class TransactionalProjectionFailed < StandardError; end
|
|
17
|
+
end
|
data/lib/funes/version.rb
CHANGED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<meta http-equiv="refresh" content="0; url=<%= latest_version %>/index.html">
|
|
6
|
+
<title>Funes Documentation</title>
|
|
7
|
+
<style>
|
|
8
|
+
body {
|
|
9
|
+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
|
10
|
+
max-width: 800px;
|
|
11
|
+
margin: 50px auto;
|
|
12
|
+
padding: 20px;
|
|
13
|
+
text-align: center;
|
|
14
|
+
}
|
|
15
|
+
.message {
|
|
16
|
+
margin-top: 100px;
|
|
17
|
+
color: #666;
|
|
18
|
+
}
|
|
19
|
+
a {
|
|
20
|
+
color: #0066cc;
|
|
21
|
+
text-decoration: none;
|
|
22
|
+
}
|
|
23
|
+
a:hover {
|
|
24
|
+
text-decoration: underline;
|
|
25
|
+
}
|
|
26
|
+
</style>
|
|
27
|
+
<script>
|
|
28
|
+
window.location.href = "<%= latest_version %>/index.html";
|
|
29
|
+
</script>
|
|
30
|
+
</head>
|
|
31
|
+
<body>
|
|
32
|
+
<div class="message">
|
|
33
|
+
<p>Redirecting to the latest version (<%= latest_version %>)...</p>
|
|
34
|
+
<p>If you are not redirected, <a href="<%= latest_version %>/index.html">click here</a>.</p>
|
|
35
|
+
</div>
|
|
36
|
+
</body>
|
|
37
|
+
</html>
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: funes-rails
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Vinícius Almeida da Silva
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-01-
|
|
11
|
+
date: 2026-01-08 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rails
|
|
@@ -50,12 +50,14 @@ files:
|
|
|
50
50
|
- config/routes.rb
|
|
51
51
|
- lib/funes.rb
|
|
52
52
|
- lib/funes/engine.rb
|
|
53
|
+
- lib/funes/transactional_projection_failed.rb
|
|
53
54
|
- lib/funes/unknown_event.rb
|
|
54
55
|
- lib/funes/unknown_materialization_model.rb
|
|
55
56
|
- lib/funes/version.rb
|
|
56
57
|
- lib/generators/funes/install_generator.rb
|
|
57
58
|
- lib/generators/funes/templates/migration.rb.tt
|
|
58
59
|
- lib/tasks/funes_tasks.rake
|
|
60
|
+
- lib/templates/docs_index.html.erb
|
|
59
61
|
homepage: https://funes.org/
|
|
60
62
|
licenses:
|
|
61
63
|
- MIT
|