multi_sync 0.0.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 +7 -0
- data/.document +3 -0
- data/.gitignore +20 -0
- data/.rubocop.yml +26 -0
- data/.travis.yml +24 -0
- data/.yardopts +6 -0
- data/CHANGELOG.md +0 -0
- data/CONTRIBUTING.md +44 -0
- data/Gemfile +17 -0
- data/LICENSE.md +20 -0
- data/README.md +134 -0
- data/Rakefile +45 -0
- data/examples/custom.rb +34 -0
- data/examples/rails-3-2/.gitignore +15 -0
- data/examples/rails-3-2/Gemfile +43 -0
- data/examples/rails-3-2/README.rdoc +261 -0
- data/examples/rails-3-2/Rakefile +7 -0
- data/examples/rails-3-2/app/assets/images/rails.png +0 -0
- data/examples/rails-3-2/app/assets/javascripts/application.js +15 -0
- data/examples/rails-3-2/app/assets/stylesheets/application.css +13 -0
- data/examples/rails-3-2/app/controllers/application_controller.rb +3 -0
- data/examples/rails-3-2/app/helpers/application_helper.rb +2 -0
- data/examples/rails-3-2/app/mailers/.gitkeep +0 -0
- data/examples/rails-3-2/app/models/.gitkeep +0 -0
- data/examples/rails-3-2/app/views/layouts/application.html.erb +14 -0
- data/examples/rails-3-2/config.ru +4 -0
- data/examples/rails-3-2/config/application.rb +62 -0
- data/examples/rails-3-2/config/asset_sync.yml +21 -0
- data/examples/rails-3-2/config/boot.rb +6 -0
- data/examples/rails-3-2/config/database.yml +25 -0
- data/examples/rails-3-2/config/environment.rb +5 -0
- data/examples/rails-3-2/config/environments/development.rb +37 -0
- data/examples/rails-3-2/config/environments/production.rb +67 -0
- data/examples/rails-3-2/config/environments/test.rb +37 -0
- data/examples/rails-3-2/config/initializers/backtrace_silencers.rb +7 -0
- data/examples/rails-3-2/config/initializers/inflections.rb +15 -0
- data/examples/rails-3-2/config/initializers/mime_types.rb +5 -0
- data/examples/rails-3-2/config/initializers/multi_sync.rb +29 -0
- data/examples/rails-3-2/config/initializers/secret_token.rb +7 -0
- data/examples/rails-3-2/config/initializers/session_store.rb +8 -0
- data/examples/rails-3-2/config/initializers/wrap_parameters.rb +14 -0
- data/examples/rails-3-2/config/locales/en.yml +5 -0
- data/examples/rails-3-2/config/routes.rb +58 -0
- data/examples/rails-3-2/db/seeds.rb +7 -0
- data/examples/rails-3-2/lib/assets/.gitkeep +0 -0
- data/examples/rails-3-2/lib/tasks/.gitkeep +0 -0
- data/examples/rails-3-2/log/.gitkeep +0 -0
- data/examples/rails-3-2/public/404.html +26 -0
- data/examples/rails-3-2/public/422.html +26 -0
- data/examples/rails-3-2/public/500.html +25 -0
- data/examples/rails-3-2/public/favicon.ico +0 -0
- data/examples/rails-3-2/public/index.html +241 -0
- data/examples/rails-3-2/public/robots.txt +5 -0
- data/examples/rails-3-2/script/rails +6 -0
- data/examples/rails-3-2/test/fixtures/.gitkeep +0 -0
- data/examples/rails-3-2/test/functional/.gitkeep +0 -0
- data/examples/rails-3-2/test/integration/.gitkeep +0 -0
- data/examples/rails-3-2/test/performance/browsing_test.rb +12 -0
- data/examples/rails-3-2/test/test_helper.rb +13 -0
- data/examples/rails-3-2/test/unit/.gitkeep +0 -0
- data/examples/rails-4-0/.gitignore +16 -0
- data/examples/rails-4-0/Gemfile +50 -0
- data/examples/rails-4-0/README.rdoc +28 -0
- data/examples/rails-4-0/Rakefile +6 -0
- data/examples/rails-4-0/app/assets/images/.keep +0 -0
- data/examples/rails-4-0/app/assets/javascripts/application.js +16 -0
- data/examples/rails-4-0/app/assets/stylesheets/application.css +13 -0
- data/examples/rails-4-0/app/controllers/application_controller.rb +5 -0
- data/examples/rails-4-0/app/controllers/concerns/.keep +0 -0
- data/examples/rails-4-0/app/helpers/application_helper.rb +2 -0
- data/examples/rails-4-0/app/mailers/.keep +0 -0
- data/examples/rails-4-0/app/models/.keep +0 -0
- data/examples/rails-4-0/app/models/concerns/.keep +0 -0
- data/examples/rails-4-0/app/views/layouts/application.html.erb +14 -0
- data/examples/rails-4-0/config.ru +4 -0
- data/examples/rails-4-0/config/application.rb +24 -0
- data/examples/rails-4-0/config/asset_sync.yml +21 -0
- data/examples/rails-4-0/config/boot.rb +4 -0
- data/examples/rails-4-0/config/database.yml +25 -0
- data/examples/rails-4-0/config/environment.rb +5 -0
- data/examples/rails-4-0/config/environments/development.rb +29 -0
- data/examples/rails-4-0/config/environments/production.rb +80 -0
- data/examples/rails-4-0/config/environments/test.rb +36 -0
- data/examples/rails-4-0/config/initializers/backtrace_silencers.rb +7 -0
- data/examples/rails-4-0/config/initializers/filter_parameter_logging.rb +4 -0
- data/examples/rails-4-0/config/initializers/inflections.rb +16 -0
- data/examples/rails-4-0/config/initializers/mime_types.rb +5 -0
- data/examples/rails-4-0/config/initializers/multi_sync.rb +29 -0
- data/examples/rails-4-0/config/initializers/secret_token.rb +12 -0
- data/examples/rails-4-0/config/initializers/session_store.rb +3 -0
- data/examples/rails-4-0/config/initializers/wrap_parameters.rb +14 -0
- data/examples/rails-4-0/config/locales/en.yml +23 -0
- data/examples/rails-4-0/config/routes.rb +56 -0
- data/examples/rails-4-0/db/seeds.rb +7 -0
- data/examples/rails-4-0/lib/assets/.keep +0 -0
- data/examples/rails-4-0/lib/tasks/.keep +0 -0
- data/examples/rails-4-0/log/.keep +0 -0
- data/examples/rails-4-0/public/404.html +58 -0
- data/examples/rails-4-0/public/422.html +58 -0
- data/examples/rails-4-0/public/500.html +57 -0
- data/examples/rails-4-0/public/favicon.ico +0 -0
- data/examples/rails-4-0/public/robots.txt +5 -0
- data/examples/rails-4-0/test/controllers/.keep +0 -0
- data/examples/rails-4-0/test/fixtures/.keep +0 -0
- data/examples/rails-4-0/test/helpers/.keep +0 -0
- data/examples/rails-4-0/test/integration/.keep +0 -0
- data/examples/rails-4-0/test/mailers/.keep +0 -0
- data/examples/rails-4-0/test/models/.keep +0 -0
- data/examples/rails-4-0/test/test_helper.rb +15 -0
- data/gemfiles/middleman-3.1.x.gemfile +5 -0
- data/gemfiles/rails-3.2.x.gemfile +5 -0
- data/gemfiles/rails-4.0.x.gemfile +5 -0
- data/lib/multi_sync.rb +92 -0
- data/lib/multi_sync/client.rb +243 -0
- data/lib/multi_sync/configuration.rb +36 -0
- data/lib/multi_sync/environment.rb +37 -0
- data/lib/multi_sync/extensions/middleman.rb +22 -0
- data/lib/multi_sync/extensions/rails.rb +20 -0
- data/lib/multi_sync/extensions/rails/asset_sync.rb +44 -0
- data/lib/multi_sync/extensions/rails/railtie.rb +11 -0
- data/lib/multi_sync/logging.rb +60 -0
- data/lib/multi_sync/mixins/log_helper.rb +9 -0
- data/lib/multi_sync/mixins/pluralize_helper.rb +15 -0
- data/lib/multi_sync/resource.rb +84 -0
- data/lib/multi_sync/resources/local_resource.rb +30 -0
- data/lib/multi_sync/resources/remote_resource.rb +32 -0
- data/lib/multi_sync/source.rb +40 -0
- data/lib/multi_sync/sources/local_source.rb +17 -0
- data/lib/multi_sync/sources/manifest_source.rb +82 -0
- data/lib/multi_sync/target.rb +34 -0
- data/lib/multi_sync/targets/aws_target.rb +80 -0
- data/lib/multi_sync/targets/local_target.rb +58 -0
- data/lib/multi_sync/version.rb +3 -0
- data/lib/tasks/multi_sync_rails.rake +15 -0
- data/multi_sync.gemspec +35 -0
- data/spec/spec_helper.rb +22 -0
- data/spec/support/celluloid.rb +14 -0
- data/spec/support/fakefs.rb +7 -0
- data/spec/support/fog.rb +25 -0
- data/spec/support/pry.rb +6 -0
- data/spec/support/timecop.rb +2 -0
- data/spec/unit/multi_sync/client_spec.rb +301 -0
- data/spec/unit/multi_sync/configuration_spec.rb +92 -0
- data/spec/unit/multi_sync/resources/local_resource_spec.rb +55 -0
- data/spec/unit/multi_sync/sources/local_source_spec.rb +48 -0
- data/spec/unit/multi_sync/sources/manifest_source_spec.rb +57 -0
- data/spec/unit/multi_sync/targets/aws_target_spec.rb +60 -0
- data/spec/unit/multi_sync/targets/local_target_spec.rb +41 -0
- data/spec/unit/multi_sync_spec.rb +55 -0
- metadata +377 -0
data/lib/multi_sync.rb
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
require 'forwardable'
|
|
2
|
+
require 'multi_sync/client'
|
|
3
|
+
require 'multi_sync/version'
|
|
4
|
+
require 'multi_sync/logging'
|
|
5
|
+
require 'multi_sync/environment'
|
|
6
|
+
require 'multi_sync/configuration'
|
|
7
|
+
|
|
8
|
+
module MultiSync
|
|
9
|
+
extend SingleForwardable
|
|
10
|
+
extend MultiSync::Logging
|
|
11
|
+
extend MultiSync::Environment
|
|
12
|
+
|
|
13
|
+
# a list of libraries, extension file and class name
|
|
14
|
+
REQUIREMENT_MAP = [
|
|
15
|
+
['rails', 'multi_sync/extensions/rails'].freeze,
|
|
16
|
+
['middleman-core', 'multi_sync/extensions/middleman'].freeze
|
|
17
|
+
]
|
|
18
|
+
|
|
19
|
+
# delegate all MultiSync::Configuration's attribute accessors to the configuration
|
|
20
|
+
def_delegators :configuration, *MultiSync::Configuration.attribute_set.map(&:name)
|
|
21
|
+
|
|
22
|
+
# delegate all MultiSync::Configuration's attribute setters to the configuration ( hacky I know... )
|
|
23
|
+
def_delegators :configuration, *(MultiSync::Configuration.attribute_set.map(&:name).map { |key| "#{key}=".to_sym })
|
|
24
|
+
|
|
25
|
+
# delegate all MultiSync::Client's attribute accessors to the configuration
|
|
26
|
+
def_delegators :client, *MultiSync::Client.attribute_set.map(&:name)
|
|
27
|
+
|
|
28
|
+
# include some public methods
|
|
29
|
+
def_delegators :client, :target, :source, :synchronize
|
|
30
|
+
|
|
31
|
+
# Configure
|
|
32
|
+
#
|
|
33
|
+
# @return [MultiSync]
|
|
34
|
+
def self.configure(&block)
|
|
35
|
+
instance_eval(&block) if block_given?
|
|
36
|
+
self
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Run
|
|
40
|
+
#
|
|
41
|
+
# @return [MultiSync]
|
|
42
|
+
def self.run(&block)
|
|
43
|
+
configure(&block).synchronize
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Prepare
|
|
47
|
+
#
|
|
48
|
+
# @return [MultiSync]
|
|
49
|
+
def self.prepare(&block)
|
|
50
|
+
configure(&block)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Fetch the MultiSync::Client
|
|
54
|
+
#
|
|
55
|
+
# @return [MultiSync::Client]
|
|
56
|
+
def self.client(options = {})
|
|
57
|
+
@client ||= MultiSync::Client.new(options)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Fetch the MultiSync::Configuration
|
|
61
|
+
#
|
|
62
|
+
# @return [MultiSync::Configuration]
|
|
63
|
+
def self.configuration(options = {})
|
|
64
|
+
@configuration ||= MultiSync::Configuration.new(options)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Reset the MultiSync::Client
|
|
68
|
+
def self.reset_client!
|
|
69
|
+
remove_instance_variable :@client if defined?(@client)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Reset the MultiSync::Configuration
|
|
73
|
+
def self.reset_configuration!
|
|
74
|
+
remove_instance_variable :@configuration if defined?(@configuration)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# Reset MultiSync::Configuration and MultiSync::Client
|
|
78
|
+
def self.reset!
|
|
79
|
+
self.reset_client!
|
|
80
|
+
self.reset_configuration!
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# by rescuing from a LoadError we can sniff out gems in use and try to automagically hook into them
|
|
84
|
+
REQUIREMENT_MAP.each do |library, extension|
|
|
85
|
+
begin
|
|
86
|
+
require library
|
|
87
|
+
require extension
|
|
88
|
+
rescue ::LoadError
|
|
89
|
+
next
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
require 'set'
|
|
2
|
+
require 'virtus'
|
|
3
|
+
require 'lazily'
|
|
4
|
+
require 'celluloid'
|
|
5
|
+
require 'multi_sync/sources/local_source'
|
|
6
|
+
require 'multi_sync/sources/manifest_source'
|
|
7
|
+
require 'multi_sync/targets/aws_target'
|
|
8
|
+
require 'multi_sync/targets/local_target'
|
|
9
|
+
require 'multi_sync/mixins/pluralize_helper'
|
|
10
|
+
|
|
11
|
+
module MultiSync
|
|
12
|
+
class Client
|
|
13
|
+
include Virtus
|
|
14
|
+
include MultiSync::Mixins::PluralizeHelper
|
|
15
|
+
|
|
16
|
+
attribute :supervisor
|
|
17
|
+
attribute :incomplete_jobs, Set, default: Set.new
|
|
18
|
+
attribute :running_jobs, Set, default: Set.new
|
|
19
|
+
attribute :complete_jobs, Set, default: Set.new
|
|
20
|
+
attribute :sources, Array, default: []
|
|
21
|
+
attribute :sync_attempts, Integer, default: 0
|
|
22
|
+
attribute :file_sync_attempts, Integer, default: 0
|
|
23
|
+
attribute :started_at, Time
|
|
24
|
+
attribute :finished_at, Time
|
|
25
|
+
|
|
26
|
+
# Initialize a new Client object
|
|
27
|
+
#
|
|
28
|
+
# @param options [Hash]
|
|
29
|
+
def initialize(options = {})
|
|
30
|
+
self.supervisor = Celluloid::SupervisionGroup.run!
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def add_target(name, options = {})
|
|
34
|
+
fail ArgumentError, "Duplicate target names detected, please rename '#{name}' to be unique" if supervisor_actor_names.include?(name)
|
|
35
|
+
clazz = MultiSync.const_get("#{options[:type].capitalize}Target")
|
|
36
|
+
supervisor.pool(clazz, as: name, args: [options], size: MultiSync.target_pool_size)
|
|
37
|
+
rescue NameError
|
|
38
|
+
MultiSync.warn "Unknown target type: #{options[:type]}"
|
|
39
|
+
raise ArgumentError, "Unknown target type: #{options[:type]}"
|
|
40
|
+
end
|
|
41
|
+
alias_method :target, :add_target
|
|
42
|
+
|
|
43
|
+
def add_source(name, options = {})
|
|
44
|
+
clazz = MultiSync.const_get("#{options[:type].capitalize}Source")
|
|
45
|
+
sources << clazz.new(options)
|
|
46
|
+
rescue NameError
|
|
47
|
+
MultiSync.warn "Unknown source type: #{options[:type]}"
|
|
48
|
+
raise ArgumentError, "Unknown source type: #{options[:type]}"
|
|
49
|
+
end
|
|
50
|
+
alias_method :source, :add_source
|
|
51
|
+
|
|
52
|
+
def synchronize
|
|
53
|
+
if sync_pointless?
|
|
54
|
+
MultiSync.debug "Preventing synchronization as there are #{sources.length} sources to sync..."
|
|
55
|
+
return
|
|
56
|
+
else
|
|
57
|
+
MultiSync.debug 'Starting synchronization...'
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
determine_sync if first_run?
|
|
61
|
+
sync_attempted
|
|
62
|
+
|
|
63
|
+
MultiSync.debug 'Scheduling jobs in the future...'
|
|
64
|
+
incomplete_jobs.delete_if do | job |
|
|
65
|
+
running_jobs << { id: job[:id], future: Celluloid::Actor[job[:target_id]].future.send(job[:method], job[:args]), method: job[:method] }
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
MultiSync.debug 'Fetching jobs from the future...'
|
|
69
|
+
running_jobs.delete_if do | job |
|
|
70
|
+
begin
|
|
71
|
+
completed_job = { id: job[:id], response: job[:future].value, method: job[:method] }
|
|
72
|
+
rescue
|
|
73
|
+
self.file_sync_attempts = file_sync_attempts + 1
|
|
74
|
+
false
|
|
75
|
+
else
|
|
76
|
+
complete_jobs << completed_job
|
|
77
|
+
true
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
finish_sync
|
|
82
|
+
finalize
|
|
83
|
+
end
|
|
84
|
+
alias_method :sync, :synchronize
|
|
85
|
+
|
|
86
|
+
def finalize
|
|
87
|
+
# if finished_at
|
|
88
|
+
# elapsed = finished_at.to_f - started_at.to_f
|
|
89
|
+
# minutes, seconds = elapsed.divmod 60.0
|
|
90
|
+
# kilobytes = get_total_file_size_from_complete_jobs / 1024.0
|
|
91
|
+
# MultiSync.debug "Sync completed in #{pluralize(minutes.round, 'minute')} and #{pluralize(seconds.round, 'second')}"
|
|
92
|
+
# MultiSync.debug "#{pluralize(complete_jobs.length, 'file')} were synchronised (#{pluralize(get_complete_deleted_jobs.length, 'deleted file')} and #{pluralize(get_complete_upload_jobs.length, 'uploaded file')}) from #{pluralize(sources.length, 'source')} to #{pluralize(supervisor.actors.length, 'target')}"
|
|
93
|
+
# MultiSync.debug "The upload weight totalled %.#{0}f #{pluralize(kilobytes, 'KB', 'KB', false)}" % kilobytes
|
|
94
|
+
# MultiSync.debug "#{pluralize(file_sync_attempts, 'failed request')} were detected and re-tried"
|
|
95
|
+
# else
|
|
96
|
+
# MultiSync.debug "Sync failed to complete with #{pluralize(incomplete_jobs.length, 'outstanding file')} to be synchronised"
|
|
97
|
+
# MultiSync.debug "#{pluralize(complete_jobs.length, 'file')} were synchronised (#{pluralize(get_complete_deleted_jobs.length, 'deleted file')} and #{pluralize(get_complete_upload_jobs.length, 'uploaded file')}) from #{pluralize(sources.length, 'source')} to #{pluralize(supervisor.actors.length, 'target')}"
|
|
98
|
+
# end
|
|
99
|
+
|
|
100
|
+
supervisor.finalize
|
|
101
|
+
end
|
|
102
|
+
alias_method :fin, :finalize
|
|
103
|
+
|
|
104
|
+
def get_complete_deleted_jobs
|
|
105
|
+
complete_jobs.select { |job| job[:method] == :delete }
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def get_complete_upload_jobs
|
|
109
|
+
complete_jobs.select { |job| job[:method] == :upload }
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def get_total_file_size_from_complete_jobs
|
|
113
|
+
total_file_size = 0
|
|
114
|
+
get_complete_upload_jobs.each do | job |
|
|
115
|
+
# MultiSync.info job[:response]
|
|
116
|
+
# MultiSync.info job[:response].determine_content_length
|
|
117
|
+
if job[:response].content_length
|
|
118
|
+
total_file_size += job[:response].content_length
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
end
|
|
122
|
+
total_file_size
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
private
|
|
126
|
+
|
|
127
|
+
def determine_sync
|
|
128
|
+
sources.lazily.each do |source|
|
|
129
|
+
|
|
130
|
+
source_files = []
|
|
131
|
+
|
|
132
|
+
starting_synchronizing_msg = "ynchronizing: '#{source.source_dir}'"
|
|
133
|
+
starting_synchronizing_msg.prepend MultiSync.force ? 'Forcefully s' : 'S'
|
|
134
|
+
MultiSync.info starting_synchronizing_msg
|
|
135
|
+
|
|
136
|
+
source_files = source.files
|
|
137
|
+
source_files.sort! # sort to make sure the source's indexes match the targets
|
|
138
|
+
|
|
139
|
+
# when no targets are specified, assume all targets
|
|
140
|
+
source.targets = supervisor_actor_names if source.targets.empty?
|
|
141
|
+
|
|
142
|
+
source.targets.lazily.each do | target_id |
|
|
143
|
+
|
|
144
|
+
missing_files = []
|
|
145
|
+
abandoned_files = []
|
|
146
|
+
outdated_files = []
|
|
147
|
+
|
|
148
|
+
MultiSync.debug "#{pluralize(source_files.length, 'file')} found from the source"
|
|
149
|
+
|
|
150
|
+
MultiSync.debug 'Fetching files from the target...'
|
|
151
|
+
|
|
152
|
+
target_files = Celluloid::Actor[target_id].files
|
|
153
|
+
target_files.sort! # sort to make sure the target's indexs match the sources
|
|
154
|
+
|
|
155
|
+
MultiSync.debug "#{pluralize(target_files.length, 'file')} found from the target"
|
|
156
|
+
|
|
157
|
+
missing_files.concat determine_missing_files(source_files, target_files)
|
|
158
|
+
missing_files_msg = "#{missing_files.length} of the files are missing"
|
|
159
|
+
missing_files_msg += ", however we're skipping them as :upload_missing_files is false" unless MultiSync.upload_missing_files
|
|
160
|
+
MultiSync.debug missing_files_msg
|
|
161
|
+
|
|
162
|
+
abandoned_files.concat determine_abandoned_files(source_files, target_files)
|
|
163
|
+
abandoned_files_msg = "#{abandoned_files.length} of the files are abandoned"
|
|
164
|
+
abandoned_files_msg += ", however we're skipping them as :delete_abandoned_files is false" unless MultiSync.delete_abandoned_files
|
|
165
|
+
MultiSync.debug abandoned_files_msg
|
|
166
|
+
|
|
167
|
+
# remove missing_files from source_files ( as we know they are missing so don't need to check them )
|
|
168
|
+
# remove abandoned_files from target_files ( as we know they are abandoned so don't need to check them )
|
|
169
|
+
outdated_files.concat determine_outdated_files(source_files - missing_files, target_files - abandoned_files)
|
|
170
|
+
MultiSync.debug "#{outdated_files.length} of the files are outdated"
|
|
171
|
+
|
|
172
|
+
# abandoned files
|
|
173
|
+
if MultiSync.delete_abandoned_files
|
|
174
|
+
abandoned_files.lazily.each do | file |
|
|
175
|
+
incomplete_jobs << { id: Celluloid.uuid, target_id: target_id, method: :delete, args: file }
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
# missing files
|
|
180
|
+
if MultiSync.upload_missing_files
|
|
181
|
+
missing_files.lazily.each do | file |
|
|
182
|
+
incomplete_jobs << { id: Celluloid.uuid, target_id: target_id, method: :upload, args: file }
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
# outdated files
|
|
187
|
+
outdated_files.lazily.each do | file |
|
|
188
|
+
incomplete_jobs << { id: Celluloid.uuid, target_id: target_id, method: :upload, args: file }
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
def determine_missing_files(source_files, target_files)
|
|
197
|
+
missing_files = (source_files - target_files)
|
|
198
|
+
missing_files
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
def determine_abandoned_files(source_files, target_files)
|
|
202
|
+
abandoned_files = (target_files - source_files)
|
|
203
|
+
abandoned_files
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
def determine_outdated_files(source_files, target_files)
|
|
207
|
+
outdated_files = []
|
|
208
|
+
|
|
209
|
+
# TODO: replace with celluloid pool of futures
|
|
210
|
+
# check each source file against the matching target_file's etag
|
|
211
|
+
source_files.lazily.each_with_index do |file, i|
|
|
212
|
+
outdated_files << file unless !MultiSync.force && file.matching_etag?(target_files[i])
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
outdated_files
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
def sync_attempted
|
|
219
|
+
self.started_at = Time.now if first_run?
|
|
220
|
+
self.sync_attempts = sync_attempts.next
|
|
221
|
+
if sync_attempts > MultiSync.max_sync_attempts
|
|
222
|
+
MultiSync.warn "Sync was attempted more then #{MultiSync.max_sync_attempts} times"
|
|
223
|
+
fail ArgumentError, "Sync was attempted more then #{MultiSync.max_sync_attempts} times"
|
|
224
|
+
end
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
def finish_sync
|
|
228
|
+
incomplete_jobs.length != 0 ? synchronize : self.finished_at = Time.now
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
def first_run?
|
|
232
|
+
sync_attempts == 0
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
def sync_pointless?
|
|
236
|
+
sources.empty?
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
def supervisor_actor_names
|
|
240
|
+
supervisor.actors.map { |actor| actor.registered_name }
|
|
241
|
+
end
|
|
242
|
+
end
|
|
243
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
require 'virtus'
|
|
2
|
+
require 'fog'
|
|
3
|
+
require 'celluloid'
|
|
4
|
+
|
|
5
|
+
module MultiSync
|
|
6
|
+
class Configuration
|
|
7
|
+
include Virtus
|
|
8
|
+
|
|
9
|
+
attribute :verbose, Boolean, default: false
|
|
10
|
+
attribute :force, Boolean, default: false
|
|
11
|
+
attribute :run_on_build, Boolean, default: true
|
|
12
|
+
attribute :delete_abandoned_files, Boolean, default: true
|
|
13
|
+
attribute :upload_missing_files, Boolean, default: true
|
|
14
|
+
attribute :target_pool_size, Integer, default: :celluloid_cores
|
|
15
|
+
attribute :max_sync_attempts, Integer, default: 3
|
|
16
|
+
attribute :credentials, Hash, default: :fog_credentials
|
|
17
|
+
|
|
18
|
+
# Initialize a new Configuration object
|
|
19
|
+
#
|
|
20
|
+
# @param options [Hash]
|
|
21
|
+
def initialize(options = {})
|
|
22
|
+
Celluloid.logger = MultiSync.test? ? nil : MultiSync.logger
|
|
23
|
+
options.each_pair do |key, value|
|
|
24
|
+
send("#{key}=", value) if attributes.keys.include?(key)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def celluloid_cores
|
|
29
|
+
Celluloid.cores
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def fog_credentials
|
|
33
|
+
Fog.credentials
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
module MultiSync
|
|
2
|
+
module Environment
|
|
3
|
+
# Retrieves the current MultiSync environment
|
|
4
|
+
#
|
|
5
|
+
# @return [String] the current environment
|
|
6
|
+
def environment
|
|
7
|
+
@environment ||= ENV['MULTI_SYNC_ENV'] || ENV['RAILS_ENV'] || ENV['RACK_ENV'] || 'development'
|
|
8
|
+
end
|
|
9
|
+
alias_method :env, :environment
|
|
10
|
+
|
|
11
|
+
# Sets the current MultiSync environment
|
|
12
|
+
#
|
|
13
|
+
# @param [String|Symbol] env the environment symbol
|
|
14
|
+
def environment=(e)
|
|
15
|
+
@environment = e.to_s
|
|
16
|
+
end
|
|
17
|
+
alias_method :env=, :environment=
|
|
18
|
+
|
|
19
|
+
# Determines if we are in a particular environment
|
|
20
|
+
#
|
|
21
|
+
# @return [Boolean] true if current environment matches, false otherwise
|
|
22
|
+
def environment?(e)
|
|
23
|
+
environment == e.to_s
|
|
24
|
+
end
|
|
25
|
+
alias_method :env?, :environment?
|
|
26
|
+
|
|
27
|
+
# Create methods for the environment shorthands
|
|
28
|
+
[:test, :development, :staging, :production].each do |e|
|
|
29
|
+
# Determines if we are in a particular environment
|
|
30
|
+
#
|
|
31
|
+
# @return [Boolean] true if current environment matches, false otherwise
|
|
32
|
+
define_method "#{e}?" do
|
|
33
|
+
environment? e
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
module MultiSync
|
|
2
|
+
module Extensions
|
|
3
|
+
class Middleman
|
|
4
|
+
MultiSync.info "Middleman -v #{::Middleman::VERSION} auto-detected"
|
|
5
|
+
|
|
6
|
+
class << self
|
|
7
|
+
def source_dir
|
|
8
|
+
File.expand_path(File.join(ENV['MM_ROOT'], 'build'))
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def destination_dir
|
|
12
|
+
''
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
MultiSync.source(:middleman,
|
|
17
|
+
type: :local,
|
|
18
|
+
source_dir: MultiSync::Extensions::Middleman.source_dir
|
|
19
|
+
)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
module MultiSync
|
|
2
|
+
module Extensions
|
|
3
|
+
require 'multi_sync/extensions/rails/railtie' if defined?(::Rails::Railtie)
|
|
4
|
+
require 'multi_sync/extensions/rails/asset_sync'
|
|
5
|
+
|
|
6
|
+
class Rails
|
|
7
|
+
MultiSync.info "Rails -v #{::Rails::VERSION::STRING} auto-detected"
|
|
8
|
+
|
|
9
|
+
class << self
|
|
10
|
+
def source_dir
|
|
11
|
+
::Rails.root.join('public', destination_dir)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def destination_dir
|
|
15
|
+
::Rails.application.config.assets.prefix.sub(/^\//, '')
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|