pub_sub_model_sync 1.0 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +3 -0
- data/Gemfile.lock +1 -3
- data/README.md +5 -2
- data/lib/pub_sub_model_sync/message_publisher.rb +6 -6
- data/lib/pub_sub_model_sync/payload_builder.rb +1 -1
- data/lib/pub_sub_model_sync/publisher_concern.rb +4 -4
- data/lib/pub_sub_model_sync/runner.rb +3 -5
- data/lib/pub_sub_model_sync/service_google.rb +1 -1
- data/lib/pub_sub_model_sync/service_kafka.rb +2 -2
- data/lib/pub_sub_model_sync/subscriber_concern.rb +5 -5
- data/lib/pub_sub_model_sync/transaction.rb +1 -1
- data/lib/pub_sub_model_sync/version.rb +1 -1
- data/samples/README.md +1 -1
- data/samples/app1/Gemfile +1 -1
- data/samples/app1/Gemfile.lock +3 -3
- data/samples/app1/config/master.key +1 -0
- data/samples/app2/Gemfile +1 -1
- data/samples/app2/Gemfile.lock +3 -3
- data/samples/app2/config/master.key +1 -0
- data/samples/app2/db/development.sqlite3 +0 -0
- metadata +5 -6
- data/samples/app1/.gitattributes +0 -8
- data/samples/app1/.gitignore +0 -28
- data/samples/app2/.gitattributes +0 -8
- data/samples/app2/.gitignore +0 -28
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6e73c2af5a62d4b0ae32ea40f3c3c369a049edfd47360a50386eeb5e4ff97cd1
|
4
|
+
data.tar.gz: 5d1892ee41ada21c9bf70bcc3601e435edfdf55d7b51b443369bf3307da60436
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 962defddfdc780ce185d01e9069485207bdf66be9b3554a1003b5ec71211c467223c288fbb6c6a59ae819a9ba37ff118a470942bdef9e69c68e94f34ff899c9a
|
7
|
+
data.tar.gz: c6e771a40a96dcdf00161aa49fbe7c1b5f283709d5b42b87421c6655e4cb9972e9f7d3bb7d203d47c9757dc681f8c755c7026447f6582ffa1f43a553ba90197a
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
+
# 1.0.1 (August 20, 2021)
|
4
|
+
- refactor: improve service exit when running in k8s
|
5
|
+
|
3
6
|
# 1.0 (June 13, 2021)
|
4
7
|
This version includes many changes that was refactored from previous version, and thus it needs manual changes to migrate into this version.
|
5
8
|
- Refactor: Subscribers param renamed `from_action` into `to_action` and added support for block or lambda
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
pub_sub_model_sync (1.0)
|
4
|
+
pub_sub_model_sync (1.0.1)
|
5
5
|
rails
|
6
6
|
|
7
7
|
GEM
|
@@ -158,8 +158,6 @@ GEM
|
|
158
158
|
nio4r (2.5.7)
|
159
159
|
nokogiri (1.11.3-x86_64-darwin)
|
160
160
|
racc (~> 1.4)
|
161
|
-
nokogiri (1.11.3-x86_64-linux)
|
162
|
-
racc (~> 1.4)
|
163
161
|
os (1.1.1)
|
164
162
|
parallel (1.20.1)
|
165
163
|
parser (3.0.1.1)
|
data/README.md
CHANGED
@@ -3,8 +3,8 @@
|
|
3
3
|
![Ruby badge](https://img.shields.io/badge/Ruby-2.4+-success.png)
|
4
4
|
![Production badge](https://img.shields.io/badge/Production-ready-success.png)
|
5
5
|
|
6
|
-
This gem permits to sync automatically models and custom data between multiple Rails applications by publishing notifications via pubsub (Google PubSub, RabbitMQ, or Apache Kafka) and automatically processed by all connected applications. Out of the scope, this gem includes transactions to keep Data consistency by processing notifications in the order they were delivered.
|
7
|
-
These notifications use JSON format to easily be decoded by subscribers (Rails applications and even other languages)
|
6
|
+
This gem permits to sync automatically models and custom data between multiple Rails applications by publishing notifications via pubsub (Google PubSub, RabbitMQ, or Apache Kafka) and automatically processed by all connected applications. Out of the scope, this gem includes transactions to keep Data consistency by processing notifications in the order they were delivered.
|
7
|
+
These notifications use JSON format to easily be decoded by subscribers (Rails applications and even other languages, soon for [Cristal-lang](https://crystal-lang.org/))
|
8
8
|
|
9
9
|
- [**PubSubModelSync**](#pubsubmodelsync)
|
10
10
|
- [**Features**](#features)
|
@@ -104,6 +104,7 @@ And then execute: $ bundle install
|
|
104
104
|
![Diagram](/docs/notifications-diagram.png?raw=true)
|
105
105
|
|
106
106
|
## **Examples**
|
107
|
+
See sample apps in [/samples](/samples/)
|
107
108
|
### **Basic Example**
|
108
109
|
```ruby
|
109
110
|
# App 1 (Publisher)
|
@@ -561,6 +562,8 @@ config.debug = true
|
|
561
562
|
- Last notification is not being delivered immediately in google pubsub (maybe force with timeout 10secs and service.deliver_messages)
|
562
563
|
- Update folder structure
|
563
564
|
- Services support to deliver multiple payloads from transactions
|
565
|
+
- Fix deprecation warnings: pub_sub_model_sync/service_google.rb:39: warning: Splitting the last argument into positional and keyword parameters is deprecated
|
566
|
+
- Add if/unless to ps_after_action
|
564
567
|
|
565
568
|
## **Q&A**
|
566
569
|
- I'm getting error "could not obtain a connection from the pool within 5.000 seconds"... what does this mean?
|
@@ -54,9 +54,9 @@ module PubSubModelSync
|
|
54
54
|
publish(payload)
|
55
55
|
end
|
56
56
|
|
57
|
-
# @param model (ActiveRecord::Base)
|
58
|
-
# @param action (Symbol
|
59
|
-
# @param settings (Hash
|
57
|
+
# @param model (ActiveRecord::Base,PubSubModelSync::PublisherConcern)
|
58
|
+
# @param action (Symbol,String @see PublishConcern::ps_publish)
|
59
|
+
# @param settings (Hash @see PayloadBuilder.settings)
|
60
60
|
def publish_model(model, action, settings = {})
|
61
61
|
log("Building payload for: #{[model, action].inspect}") if config.debug
|
62
62
|
payload = PubSubModelSync::PayloadBuilder.new(model, action, settings).call
|
@@ -80,7 +80,7 @@ module PubSubModelSync
|
|
80
80
|
end
|
81
81
|
|
82
82
|
def connector_publish(payload)
|
83
|
-
log("Publishing message #{payload
|
83
|
+
log("Publishing message #{[payload]}...") if config.debug
|
84
84
|
connector.publish(payload)
|
85
85
|
log("Published message: #{[payload]}")
|
86
86
|
config.on_after_publish.call(payload)
|
@@ -99,7 +99,7 @@ module PubSubModelSync
|
|
99
99
|
|
100
100
|
def ensure_publish(payload)
|
101
101
|
cancelled = config.on_before_publish.call(payload) == :cancel
|
102
|
-
log("Publish cancelled by config.on_before_publish: #{payload}") if config.debug && cancelled
|
102
|
+
log("Publish cancelled by config.on_before_publish: #{[payload]}") if config.debug && cancelled
|
103
103
|
!cancelled
|
104
104
|
end
|
105
105
|
|
@@ -110,7 +110,7 @@ module PubSubModelSync
|
|
110
110
|
def ensure_model_publish(model, action, payload)
|
111
111
|
res_before = model.ps_before_publish(action, payload)
|
112
112
|
cancelled = res_before == :cancel
|
113
|
-
log("Publish cancelled by model.ps_before_publish: #{payload}") if config.debug && cancelled
|
113
|
+
log("Publish cancelled by model.ps_before_publish: #{[payload]}") if config.debug && cancelled
|
114
114
|
!cancelled
|
115
115
|
end
|
116
116
|
|
@@ -4,7 +4,7 @@ module PubSubModelSync
|
|
4
4
|
class PayloadBuilder < PubSubModelSync::Base
|
5
5
|
attr_accessor :model, :action, :data, :mapping, :headers, :as_klass
|
6
6
|
|
7
|
-
# @param model (ActiveRecord::Base)
|
7
|
+
# @param model (ActiveRecord::Base,PubSubModelSync::PublisherConcern)
|
8
8
|
# @param action (@see PublishConcern::ps_publish)
|
9
9
|
# @param settings (@see PublishConcern::ps_publish): { data:, mapping:, headers:, as_klass: }
|
10
10
|
def initialize(model, action, settings = {})
|
@@ -18,14 +18,14 @@ module PubSubModelSync
|
|
18
18
|
alias ps_after_sync ps_after_publish # @deprecated
|
19
19
|
|
20
20
|
# Delivers a notification via pubsub
|
21
|
-
# @param action (
|
21
|
+
# @param action (Symbol,String) Sample: create|update|save|destroy|<any_other_key>
|
22
22
|
# @param mapping? (Array<String>) If present will generate data using the mapping and added to the payload.
|
23
23
|
# Sample: ["id", "full_name:name"]
|
24
|
-
# @param data? (Hash
|
24
|
+
# @param data? (Hash,Symbol,Proc)
|
25
25
|
# Hash: Data to be added to the payload
|
26
26
|
# Symbol: Method name to be called to retrieve payload data (must return a hash value, receives :action name)
|
27
27
|
# Proc: Block to be called to retrieve payload data
|
28
|
-
# @param headers? (Hash
|
28
|
+
# @param headers? (Hash,Symbol,Proc): (All available attributes in @Payload.headers)
|
29
29
|
# Hash: Data that will be merged with default header values
|
30
30
|
# Symbol: Method name that will be called to retrieve header values (must return a hash, receives :action name)
|
31
31
|
# Proc: Block to be called to retrieve header values
|
@@ -57,7 +57,7 @@ module PubSubModelSync
|
|
57
57
|
klass.publish_data((as_klass || name).to_s, data, action.to_sym, headers: headers)
|
58
58
|
end
|
59
59
|
|
60
|
-
# @param crud_actions (Symbol
|
60
|
+
# @param crud_actions (Symbol,Array<Symbol>): :create, :update, :destroy
|
61
61
|
# @param method_name (Symbol, optional) method to be called
|
62
62
|
def ps_after_action(crud_actions, method_name = nil, &block)
|
63
63
|
actions = Array(crud_actions).map(&:to_sym)
|
@@ -3,7 +3,6 @@
|
|
3
3
|
require 'active_support/core_ext/module'
|
4
4
|
module PubSubModelSync
|
5
5
|
class Runner
|
6
|
-
class ShutDown < StandardError; end
|
7
6
|
delegate :preload_listeners, to: :class
|
8
7
|
attr_accessor :connector
|
9
8
|
|
@@ -12,11 +11,10 @@ module PubSubModelSync
|
|
12
11
|
end
|
13
12
|
|
14
13
|
def run
|
14
|
+
at_exit { connector.stop }
|
15
15
|
trap_signals!
|
16
16
|
preload_listeners
|
17
17
|
start_listeners
|
18
|
-
rescue ShutDown
|
19
|
-
connector.stop
|
20
18
|
end
|
21
19
|
|
22
20
|
def self.preload_listeners
|
@@ -32,8 +30,8 @@ module PubSubModelSync
|
|
32
30
|
|
33
31
|
def trap_signals!
|
34
32
|
handler = proc do |signal|
|
35
|
-
puts "received #{Signal.signame(signal)}"
|
36
|
-
|
33
|
+
puts "PS_MSYNC ==> received #{Signal.signame(signal)}"
|
34
|
+
exit
|
37
35
|
end
|
38
36
|
%w[INT QUIT TERM].each { |signal| Signal.trap(signal, handler) }
|
39
37
|
end
|
@@ -76,8 +76,8 @@ module PubSubModelSync
|
|
76
76
|
end
|
77
77
|
|
78
78
|
# Check topic existence, create if missing topic
|
79
|
-
# @param names (Array<String
|
80
|
-
# @return (Array
|
79
|
+
# @param names (Array<String>,String)
|
80
|
+
# @return (Array,String) return @param names
|
81
81
|
def ensure_topics(names)
|
82
82
|
missing_topics = Array(names) - (@known_topics || service.topics)
|
83
83
|
missing_topics.each do |name|
|
@@ -9,16 +9,16 @@ module PubSubModelSync
|
|
9
9
|
end
|
10
10
|
|
11
11
|
module ClassMethods
|
12
|
-
# @param actions (Symbol
|
12
|
+
# @param actions (Symbol,Array<Symbol>) Notification.action name: save|create|update|destroy|<any_other_action>
|
13
13
|
# @param mapping (Array<String,Symbol>) Attributes mapping with aliasing support, sample: ["id", "full_name:name"]
|
14
14
|
# @param settings (Hash<:from_klass, :to_action, :id, :if, :unless>)
|
15
15
|
# from_klass (String) Notification.class name
|
16
|
-
# to_action (Symbol
|
16
|
+
# to_action (Symbol,Proc):
|
17
17
|
# Symbol: Method to process the notification
|
18
18
|
# Proc: Block to process the notification
|
19
|
-
# id (Symbol
|
20
|
-
# if (Symbol
|
21
|
-
# unless (Symbol
|
19
|
+
# id (Symbol,Array<Symbol,String>) attribute(s) DB primary identifier(s). Supports for mapping format.
|
20
|
+
# if (Symbol,Proc,Array<Symbol>) Method or block called as the conformation before calling the callback
|
21
|
+
# unless (Symbol,Proc,Array<Symbol>) Method or block called as the negation before calling the callback
|
22
22
|
def ps_subscribe(actions, mapping = [], settings = {}, &block)
|
23
23
|
settings[:to_action] ||= block if block
|
24
24
|
Array(actions).map do |action|
|
@@ -5,7 +5,7 @@ module PubSubModelSync
|
|
5
5
|
PUBLISHER_KLASS = PubSubModelSync::MessagePublisher
|
6
6
|
attr_accessor :key, :payloads, :max_buffer, :root, :children, :finished
|
7
7
|
|
8
|
-
# @param key (String
|
8
|
+
# @param key (String,Null) Transaction key, if empty will use the ordering_key from first payload
|
9
9
|
# @param max_buffer (Integer) Once this quantity of notifications is reached, then all notifications
|
10
10
|
# will immediately be delivered.
|
11
11
|
# Note: There is no way to rollback delivered notifications if current transaction fails
|
data/samples/README.md
CHANGED
@@ -6,7 +6,7 @@ This is a sample to sync information between rails applications using RabbitMQ
|
|
6
6
|
```docker network create shared_app_services```
|
7
7
|
|
8
8
|
* Start RabbitMQ server
|
9
|
-
```docker-compose up pubsub```
|
9
|
+
```cd samples/app1 && docker-compose up pubsub```
|
10
10
|
|
11
11
|
* In another tab access to App1 to publish notifications (Wait for step 2)
|
12
12
|
- Access to the application
|
data/samples/app1/Gemfile
CHANGED
@@ -18,7 +18,7 @@ gem 'bootsnap', '>= 1.4.4', require: false
|
|
18
18
|
# Use Rack CORS for handling Cross-Origin Resource Sharing (CORS), making cross-origin AJAX possible
|
19
19
|
# gem 'rack-cors'
|
20
20
|
|
21
|
-
gem 'pub_sub_model_sync'
|
21
|
+
gem 'pub_sub_model_sync', '>= 1.0'
|
22
22
|
gem 'bunny' # to use rabbit-mq pub/sub service
|
23
23
|
gem 'annotate'
|
24
24
|
|
data/samples/app1/Gemfile.lock
CHANGED
@@ -96,7 +96,7 @@ GEM
|
|
96
96
|
nokogiri (1.11.3)
|
97
97
|
mini_portile2 (~> 2.5.0)
|
98
98
|
racc (~> 1.4)
|
99
|
-
pub_sub_model_sync (1.0
|
99
|
+
pub_sub_model_sync (1.0)
|
100
100
|
rails
|
101
101
|
puma (5.3.1)
|
102
102
|
nio4r (~> 2.0)
|
@@ -160,7 +160,7 @@ DEPENDENCIES
|
|
160
160
|
bunny
|
161
161
|
byebug
|
162
162
|
listen (~> 3.3)
|
163
|
-
pub_sub_model_sync (
|
163
|
+
pub_sub_model_sync (>= 1.0)
|
164
164
|
puma (~> 5.0)
|
165
165
|
rails (~> 6.1.3, >= 6.1.3.2)
|
166
166
|
spring
|
@@ -168,4 +168,4 @@ DEPENDENCIES
|
|
168
168
|
tzinfo-data
|
169
169
|
|
170
170
|
BUNDLED WITH
|
171
|
-
2.
|
171
|
+
2.2.17
|
@@ -0,0 +1 @@
|
|
1
|
+
f76db08751757e296d844ca18dcdb0a1
|
data/samples/app2/Gemfile
CHANGED
@@ -18,7 +18,7 @@ gem 'bootsnap', '>= 1.4.4', require: false
|
|
18
18
|
# Use Rack CORS for handling Cross-Origin Resource Sharing (CORS), making cross-origin AJAX possible
|
19
19
|
# gem 'rack-cors'
|
20
20
|
|
21
|
-
gem 'pub_sub_model_sync'
|
21
|
+
gem 'pub_sub_model_sync', '>= 1.0'
|
22
22
|
gem 'bunny' # to use rabbit-mq pub/sub service
|
23
23
|
gem 'annotate'
|
24
24
|
|
data/samples/app2/Gemfile.lock
CHANGED
@@ -96,7 +96,7 @@ GEM
|
|
96
96
|
nokogiri (1.11.3)
|
97
97
|
mini_portile2 (~> 2.5.0)
|
98
98
|
racc (~> 1.4)
|
99
|
-
pub_sub_model_sync (1.0
|
99
|
+
pub_sub_model_sync (1.0)
|
100
100
|
rails
|
101
101
|
puma (5.3.1)
|
102
102
|
nio4r (~> 2.0)
|
@@ -160,7 +160,7 @@ DEPENDENCIES
|
|
160
160
|
bunny
|
161
161
|
byebug
|
162
162
|
listen (~> 3.3)
|
163
|
-
pub_sub_model_sync (
|
163
|
+
pub_sub_model_sync (>= 1.0)
|
164
164
|
puma (~> 5.0)
|
165
165
|
rails (~> 6.1.3, >= 6.1.3.2)
|
166
166
|
spring
|
@@ -168,4 +168,4 @@ DEPENDENCIES
|
|
168
168
|
tzinfo-data
|
169
169
|
|
170
170
|
BUNDLED WITH
|
171
|
-
2.
|
171
|
+
2.2.17
|
@@ -0,0 +1 @@
|
|
1
|
+
ca702da1b8c8f8405ed03739ca90b0e5
|
Binary file
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pub_sub_model_sync
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 1.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Owen
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-08-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -134,8 +134,6 @@ files:
|
|
134
134
|
- lib/pub_sub_model_sync/version.rb
|
135
135
|
- pub_sub_model_sync.gemspec
|
136
136
|
- samples/README.md
|
137
|
-
- samples/app1/.gitattributes
|
138
|
-
- samples/app1/.gitignore
|
139
137
|
- samples/app1/Dockerfile
|
140
138
|
- samples/app1/Gemfile
|
141
139
|
- samples/app1/Gemfile.lock
|
@@ -168,6 +166,7 @@ files:
|
|
168
166
|
- samples/app1/config/initializers/pubsub.rb
|
169
167
|
- samples/app1/config/initializers/wrap_parameters.rb
|
170
168
|
- samples/app1/config/locales/en.yml
|
169
|
+
- samples/app1/config/master.key
|
171
170
|
- samples/app1/config/puma.rb
|
172
171
|
- samples/app1/config/routes.rb
|
173
172
|
- samples/app1/config/spring.rb
|
@@ -177,8 +176,6 @@ files:
|
|
177
176
|
- samples/app1/db/seeds.rb
|
178
177
|
- samples/app1/docker-compose.yml
|
179
178
|
- samples/app1/log/.keep
|
180
|
-
- samples/app2/.gitattributes
|
181
|
-
- samples/app2/.gitignore
|
182
179
|
- samples/app2/Dockerfile
|
183
180
|
- samples/app2/Gemfile
|
184
181
|
- samples/app2/Gemfile.lock
|
@@ -211,9 +208,11 @@ files:
|
|
211
208
|
- samples/app2/config/initializers/pubsub.rb
|
212
209
|
- samples/app2/config/initializers/wrap_parameters.rb
|
213
210
|
- samples/app2/config/locales/en.yml
|
211
|
+
- samples/app2/config/master.key
|
214
212
|
- samples/app2/config/puma.rb
|
215
213
|
- samples/app2/config/routes.rb
|
216
214
|
- samples/app2/config/spring.rb
|
215
|
+
- samples/app2/db/development.sqlite3
|
217
216
|
- samples/app2/db/migrate/20210513080956_create_customers.rb
|
218
217
|
- samples/app2/db/migrate/20210513135203_create_posts.rb
|
219
218
|
- samples/app2/db/schema.rb
|
data/samples/app1/.gitattributes
DELETED
data/samples/app1/.gitignore
DELETED
@@ -1,28 +0,0 @@
|
|
1
|
-
# See https://help.github.com/articles/ignoring-files for more about ignoring files.
|
2
|
-
#
|
3
|
-
# If you find yourself ignoring temporary files generated by your text editor
|
4
|
-
# or operating system, you probably want to add a global ignore instead:
|
5
|
-
# git config --global core.excludesfile '~/.gitignore_global'
|
6
|
-
|
7
|
-
# Ignore bundler config.
|
8
|
-
/.bundle
|
9
|
-
|
10
|
-
# Ignore the default SQLite database.
|
11
|
-
/db/*.sqlite3
|
12
|
-
/db/*.sqlite3-*
|
13
|
-
|
14
|
-
# Ignore all logfiles and tempfiles.
|
15
|
-
/log/*
|
16
|
-
/tmp/*
|
17
|
-
!/log/.keep
|
18
|
-
!/tmp/.keep
|
19
|
-
|
20
|
-
# Ignore pidfiles, but keep the directory.
|
21
|
-
/tmp/pids/*
|
22
|
-
!/tmp/pids/
|
23
|
-
!/tmp/pids/.keep
|
24
|
-
|
25
|
-
.byebug_history
|
26
|
-
|
27
|
-
# Ignore master key for decrypting credentials and more.
|
28
|
-
/config/master.key
|
data/samples/app2/.gitattributes
DELETED
data/samples/app2/.gitignore
DELETED
@@ -1,28 +0,0 @@
|
|
1
|
-
# See https://help.github.com/articles/ignoring-files for more about ignoring files.
|
2
|
-
#
|
3
|
-
# If you find yourself ignoring temporary files generated by your text editor
|
4
|
-
# or operating system, you probably want to add a global ignore instead:
|
5
|
-
# git config --global core.excludesfile '~/.gitignore_global'
|
6
|
-
|
7
|
-
# Ignore bundler config.
|
8
|
-
/.bundle
|
9
|
-
|
10
|
-
# Ignore the default SQLite database.
|
11
|
-
/db/*.sqlite3
|
12
|
-
/db/*.sqlite3-*
|
13
|
-
|
14
|
-
# Ignore all logfiles and tempfiles.
|
15
|
-
/log/*
|
16
|
-
/tmp/*
|
17
|
-
!/log/.keep
|
18
|
-
!/tmp/.keep
|
19
|
-
|
20
|
-
# Ignore pidfiles, but keep the directory.
|
21
|
-
/tmp/pids/*
|
22
|
-
!/tmp/pids/
|
23
|
-
!/tmp/pids/.keep
|
24
|
-
|
25
|
-
.byebug_history
|
26
|
-
|
27
|
-
# Ignore master key for decrypting credentials and more.
|
28
|
-
/config/master.key
|