multi_sync 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +1 -0
- data/README.md +100 -56
- data/lib/multi_sync/attributes/pathname.rb +12 -0
- data/lib/multi_sync/client.rb +34 -36
- data/lib/multi_sync/configuration.rb +3 -5
- data/lib/multi_sync/extensions/middleman.rb +1 -1
- data/lib/multi_sync/extensions/rails/asset_sync.rb +2 -2
- data/lib/multi_sync/extensions/rails.rb +1 -1
- data/lib/multi_sync/logging.rb +2 -2
- data/lib/multi_sync/resource.rb +15 -32
- data/lib/multi_sync/resources/local_resource.rb +1 -0
- data/lib/multi_sync/resources/remote_resource.rb +1 -4
- data/lib/multi_sync/source.rb +10 -22
- data/lib/multi_sync/sources/manifest_source.rb +2 -2
- data/lib/multi_sync/target.rb +5 -16
- data/lib/multi_sync/targets/aws_target.rb +7 -10
- data/lib/multi_sync/targets/local_target.rb +6 -9
- data/lib/multi_sync/version.rb +1 -1
- data/lib/multi_sync.rb +1 -1
- data/lib/tasks/multi_sync_rails.rake +8 -2
- data/multi_sync.gemspec +2 -2
- data/spec/unit/multi_sync/client_spec.rb +3 -0
- data/spec/unit/multi_sync/resources/local_resource_spec.rb +6 -8
- data/spec/unit/multi_sync_spec.rb +0 -8
- metadata +7 -106
- data/examples/custom.rb +0 -34
- data/examples/rails-3-2/.gitignore +0 -15
- data/examples/rails-3-2/Gemfile +0 -43
- data/examples/rails-3-2/README.rdoc +0 -261
- data/examples/rails-3-2/Rakefile +0 -7
- data/examples/rails-3-2/app/assets/images/rails.png +0 -0
- data/examples/rails-3-2/app/assets/javascripts/application.js +0 -15
- data/examples/rails-3-2/app/assets/stylesheets/application.css +0 -13
- data/examples/rails-3-2/app/controllers/application_controller.rb +0 -3
- data/examples/rails-3-2/app/helpers/application_helper.rb +0 -2
- 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 +0 -14
- data/examples/rails-3-2/config/application.rb +0 -62
- data/examples/rails-3-2/config/asset_sync.yml +0 -21
- data/examples/rails-3-2/config/boot.rb +0 -6
- data/examples/rails-3-2/config/database.yml +0 -25
- data/examples/rails-3-2/config/environment.rb +0 -5
- data/examples/rails-3-2/config/environments/development.rb +0 -37
- data/examples/rails-3-2/config/environments/production.rb +0 -67
- data/examples/rails-3-2/config/environments/test.rb +0 -37
- data/examples/rails-3-2/config/initializers/backtrace_silencers.rb +0 -7
- data/examples/rails-3-2/config/initializers/inflections.rb +0 -15
- data/examples/rails-3-2/config/initializers/mime_types.rb +0 -5
- data/examples/rails-3-2/config/initializers/multi_sync.rb +0 -29
- data/examples/rails-3-2/config/initializers/secret_token.rb +0 -7
- data/examples/rails-3-2/config/initializers/session_store.rb +0 -8
- data/examples/rails-3-2/config/initializers/wrap_parameters.rb +0 -14
- data/examples/rails-3-2/config/locales/en.yml +0 -5
- data/examples/rails-3-2/config/routes.rb +0 -58
- data/examples/rails-3-2/config.ru +0 -4
- data/examples/rails-3-2/db/seeds.rb +0 -7
- 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 +0 -26
- data/examples/rails-3-2/public/422.html +0 -26
- data/examples/rails-3-2/public/500.html +0 -25
- data/examples/rails-3-2/public/favicon.ico +0 -0
- data/examples/rails-3-2/public/index.html +0 -241
- data/examples/rails-3-2/public/robots.txt +0 -5
- data/examples/rails-3-2/script/rails +0 -6
- 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 +0 -12
- data/examples/rails-3-2/test/test_helper.rb +0 -13
- data/examples/rails-3-2/test/unit/.gitkeep +0 -0
- data/examples/rails-4-0/.gitignore +0 -16
- data/examples/rails-4-0/Gemfile +0 -50
- data/examples/rails-4-0/README.rdoc +0 -28
- data/examples/rails-4-0/Rakefile +0 -6
- data/examples/rails-4-0/app/assets/images/.keep +0 -0
- data/examples/rails-4-0/app/assets/javascripts/application.js +0 -16
- data/examples/rails-4-0/app/assets/stylesheets/application.css +0 -13
- data/examples/rails-4-0/app/controllers/application_controller.rb +0 -5
- data/examples/rails-4-0/app/controllers/concerns/.keep +0 -0
- data/examples/rails-4-0/app/helpers/application_helper.rb +0 -2
- 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 +0 -14
- data/examples/rails-4-0/bin/bundle +0 -3
- data/examples/rails-4-0/bin/rails +0 -4
- data/examples/rails-4-0/bin/rake +0 -4
- data/examples/rails-4-0/config/application.rb +0 -24
- data/examples/rails-4-0/config/asset_sync.yml +0 -21
- data/examples/rails-4-0/config/boot.rb +0 -4
- data/examples/rails-4-0/config/database.yml +0 -25
- data/examples/rails-4-0/config/environment.rb +0 -5
- data/examples/rails-4-0/config/environments/development.rb +0 -29
- data/examples/rails-4-0/config/environments/production.rb +0 -80
- data/examples/rails-4-0/config/environments/test.rb +0 -36
- data/examples/rails-4-0/config/initializers/backtrace_silencers.rb +0 -7
- data/examples/rails-4-0/config/initializers/filter_parameter_logging.rb +0 -4
- data/examples/rails-4-0/config/initializers/inflections.rb +0 -16
- data/examples/rails-4-0/config/initializers/mime_types.rb +0 -5
- data/examples/rails-4-0/config/initializers/multi_sync.rb +0 -29
- data/examples/rails-4-0/config/initializers/secret_token.rb +0 -12
- data/examples/rails-4-0/config/initializers/session_store.rb +0 -3
- data/examples/rails-4-0/config/initializers/wrap_parameters.rb +0 -14
- data/examples/rails-4-0/config/locales/en.yml +0 -23
- data/examples/rails-4-0/config/routes.rb +0 -56
- data/examples/rails-4-0/config.ru +0 -4
- data/examples/rails-4-0/db/seeds.rb +0 -7
- 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 +0 -58
- data/examples/rails-4-0/public/422.html +0 -58
- data/examples/rails-4-0/public/500.html +0 -57
- data/examples/rails-4-0/public/favicon.ico +0 -0
- data/examples/rails-4-0/public/robots.txt +0 -5
- 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 +0 -15
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 580e01265e2768d6a728b4dc3b29adad42874e7b
|
4
|
+
data.tar.gz: 09575ab0fa096363ef1deeeb94a435e6dc1a5605
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5c729e36efd763755ca1d1f85827fc986a7e90823ab1199c900620d8f012f2f7182ce432d91fdf3292063f3ab74f11a146690814551c074329d33c3653dc2b4f
|
7
|
+
data.tar.gz: 3968ae066b80ef8fb122c7b90aa7817ec1e7b8646091d7ff5af8e9832bcaa9da506e8dc746800664e49df5918bc1874a847e6cc1768c41c37f281a0e8677f81a
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,12 +1,16 @@
|
|
1
1
|
# MultiSync
|
2
2
|
|
3
|
-
:heavy_exclamation_mark: **a WIP
|
3
|
+
:heavy_exclamation_mark: **currently a functioning WIP thats not quite finished yet but its close!** :heavy_exclamation_mark:
|
4
4
|
|
5
5
|
A flexible synchronisation library for your assets.
|
6
6
|
|
7
|
-
|
7
|
+
`MultiSync` stands on the shoulders of giants. On one side is [Celluloid](http://celluloid.io) allowing for the synchronisation of assets to be highly parallel. On the other is [Fog::Storage](https://github.com/fog/fog) allowing `MulitSync` to support [various well known storage services](#storage-services).
|
8
8
|
|
9
|
-
|
9
|
+
What that means is when your configuring `MultiSync` your creating various pools of workers which then distrubute the work behind synchronising your assets. Meaning that when your site has thousands of files, you get alot more :boom: for your :dollar: in less :alarm_clock:.
|
10
|
+
|
11
|
+
`MultiSync` tries to expose its asset synchronisation in a flexible way which should allow you to define how and where your assets live. Where possible though, `MultiSync` will try to provide support for [various well known libraries](#supported-libraries).
|
12
|
+
|
13
|
+
Listed below are examples of how to get setup and started.
|
10
14
|
|
11
15
|
## Installation
|
12
16
|
|
@@ -17,7 +21,7 @@ gem 'multi_sync', '~> 0.0.1'
|
|
17
21
|
```ruby
|
18
22
|
require 'multi_sync'
|
19
23
|
|
20
|
-
MultiSync.
|
24
|
+
MultiSync.configure do |config|
|
21
25
|
# config.verbose = false # turn on verbose logging (defaults to false)
|
22
26
|
# config.force = false # force syncing of outdated_files (defaults to false)
|
23
27
|
# config.run_on_build = true # when within a framework which `builds` assets, whether to sync afterwards (defaults to true)
|
@@ -25,79 +29,119 @@ MultiSync.configuration do |config|
|
|
25
29
|
# config.delete_abandoned_files = true # when an abondoned file is found whether to remove it (defaults to true)
|
26
30
|
# config.upload_missing_files = true # when a missing file is found whether to upload it (defaults to true)
|
27
31
|
# config.target_pool_size = 8 # how many threads you would like to open for each target (defaults to the amount of CPU core's your machine has)
|
28
|
-
# config.max_sync_attempts =
|
32
|
+
# config.max_sync_attempts = 3 # how many times a file should be retried if there was an error during sync (defaults to 3)
|
29
33
|
end
|
30
34
|
```
|
31
35
|
|
32
36
|
### Fog credentials support
|
33
37
|
|
34
|
-
`MultiSync` supports utilising [Fog Credentials](http://fog.io/about/getting_started.html#credentials). Simply specify either a `FOG_RC` or `.fog` and we'll use it as the base for any credentials used in a target
|
38
|
+
`MultiSync` supports utilising [Fog Credentials](http://fog.io/about/getting_started.html#credentials). Simply specify either a `FOG_RC` or `.fog` and we'll use it as the base for any `:credentials` used in a `target`.
|
35
39
|
|
36
40
|
## Features / Usage Examples
|
37
41
|
|
38
|
-
|
39
|
-
|
40
|
-
Many people use [AssetSync](https://github.com/rumblelabs/asset_sync) and for `MultiSync`'s first release compatibility with it has been built in. When within a `Rails` environment `MultiSync` will check for `asset_sync.yml` and read in its settings. You should be able to simply require `multi_sync` and try things out.
|
42
|
+
`MultiSync` in its simplist form consists of three objects. `sources`, `resources` and `targets`. A `source` defines how and where a list of files (or `resources`) can be found. A `resource` represents a file from a `source` with additional properties (such as how to compare them). A `target` is destination which `resources` can be synchronised against.
|
41
43
|
|
42
|
-
|
44
|
+
### Source
|
43
45
|
|
44
|
-
|
45
|
-
- `AssetSync`'s gzip_compression hack
|
46
|
+
A source takes two arguments. The first is a `name` to reference this source by and the second is a `Hash` of configuration detailed below.
|
46
47
|
|
47
|
-
|
48
|
+
| Key | Type | Default | Description |
|
49
|
+
| :-- | :--- | :------ | :---------- |
|
50
|
+
| `type` | `Symbol` | `nil` | The `type` of source this is (`:local`, `:manifest`) |
|
51
|
+
| `source_dir` | `Pathname`, `String` | `nil` | The location this source should use |
|
52
|
+
| `resource_options` | `Hash` | `nil` | A hash of options for this source`s resources |
|
53
|
+
| `targets` | `Symbol`, `Array` | All targets | The target(s) this source should sync against |
|
54
|
+
| `include` | `String` ([shell glob](http://www.ruby-doc.org/core-2.1.1/Dir.html#method-c-glob)) | `**/*` | A shell globe to use for inclusion |
|
55
|
+
| `exclude` | `String` ([shell glob](http://www.ruby-doc.org/core-2.1.1/Dir.html#method-c-glob)) | `nil` | A shell globe to use for exclusion |
|
56
|
+
___
|
48
57
|
|
49
|
-
|
58
|
+
```ruby
|
59
|
+
# A source named ':build' which is ':local' and will use all files within '../build'
|
60
|
+
source :build, {
|
61
|
+
type: :local,
|
62
|
+
source_dir: '../build'
|
63
|
+
}
|
64
|
+
```
|
65
|
+
___
|
50
66
|
|
51
67
|
```ruby
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
target :assets, {
|
61
|
-
type: :aws, # :aws is the target's type, current options are :aws
|
62
|
-
target_dir: 'your_aws_bucket',
|
63
|
-
destination_dir: 'an_optional_directory_inside_your_aws_bucket',
|
64
|
-
credentials: {
|
65
|
-
region: 'us-east-1',
|
66
|
-
aws_access_key_id: 'super_secret',
|
67
|
-
aws_secret_access_key: 'super_secret'
|
68
|
-
}
|
69
|
-
}
|
68
|
+
# A source named ':assets' which will use a Sprockets ':manifest' within '../public/assets'
|
69
|
+
source :assets, {
|
70
|
+
type: :manifest,
|
71
|
+
source_dir: '../public/assets'
|
72
|
+
}
|
73
|
+
```
|
74
|
+
___
|
70
75
|
|
71
|
-
|
76
|
+
```ruby
|
77
|
+
# A source named ':video_assets' which is `:local' and will use all files
|
78
|
+
# within '../build' including only 'mp4, mpg, mov'
|
79
|
+
source :video_assets, {
|
80
|
+
type: :local,
|
81
|
+
source_dir: '../build',
|
82
|
+
include: '*.{mp4,mpg,mov}'
|
83
|
+
}
|
72
84
|
```
|
85
|
+
___
|
73
86
|
|
74
|
-
|
87
|
+
```ruby
|
88
|
+
# A source named ':no_images' which is `:local' and will use all files
|
89
|
+
# within '../build' excluding any 'jpg, gif, png'
|
90
|
+
source :no_images, {
|
91
|
+
type: :local,
|
92
|
+
source_dir: '../build',
|
93
|
+
exclude: '*.{jpg,gif,png}'
|
94
|
+
}
|
95
|
+
```
|
96
|
+
___
|
75
97
|
|
76
|
-
|
98
|
+
```ruby
|
99
|
+
# A source named ':www' which will use a Sprockets ':manifest'
|
100
|
+
# within '../public/assets' excluding any 'jpg, gif, png' files
|
101
|
+
# and only synchronising with a target named `:www`
|
102
|
+
source :www, {
|
103
|
+
type: :manifest,
|
104
|
+
source_dir: '../public/assets',
|
105
|
+
exclude: '*.{jpg,gif,png}',
|
106
|
+
targets: :www
|
107
|
+
}
|
108
|
+
```
|
109
|
+
___
|
77
110
|
|
78
111
|
```ruby
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
aws_secret_access_key: 'super_secret'
|
95
|
-
}
|
96
|
-
}
|
112
|
+
# A source named ':image_assets' which will use a Sprockets ':manifest'
|
113
|
+
# within '../public/assets' including only 'jpg, gif, png' files
|
114
|
+
# which sets `cache_control` and `expires` headers and
|
115
|
+
# synchronises with the target `:images`
|
116
|
+
source :image_assets, {
|
117
|
+
type: :manifest,
|
118
|
+
source_dir: '../public/assets',
|
119
|
+
include: '*.{jpg,gif,png}',
|
120
|
+
resource_options: {
|
121
|
+
cache_control: 'public, max-age=31557600',
|
122
|
+
expires: CGI.rfc1123_date(Time.now + 31557600)
|
123
|
+
},
|
124
|
+
targets: :images
|
125
|
+
}
|
126
|
+
```
|
97
127
|
|
98
|
-
|
128
|
+
### Target
|
129
|
+
|
130
|
+
```ruby
|
131
|
+
...
|
99
132
|
```
|
100
133
|
|
134
|
+
|
135
|
+
## Supported Libraries
|
136
|
+
|
137
|
+
- [Rails](https://github.com/karlfreeman/multi_sync/wiki/rails)
|
138
|
+
- Sinatra (WIP)
|
139
|
+
- Middleman (WIP)
|
140
|
+
- Jekyll (WIP)
|
141
|
+
- Nanoc (WIP)
|
142
|
+
- [POR](https://github.com/karlfreeman/multi_sync/wiki/por)
|
143
|
+
- Rake (WIP)
|
144
|
+
|
101
145
|
## Badges
|
102
146
|
|
103
147
|
[![Gem Version](http://img.shields.io/gem/v/multi_sync.svg)][gem]
|
@@ -110,8 +154,8 @@ end
|
|
110
154
|
Behind the scenes we're using [Fog::Storage](http://fog.io/storage) which allows us to support the most popular storage providers
|
111
155
|
|
112
156
|
- [Amazon S3](http://aws.amazon.com/s3)
|
113
|
-
- [Rackspace CloudFiles](http://www.rackspace.com/cloud/files)
|
114
|
-
- [Google Cloud Storage](https://developers.google.com/storage)
|
157
|
+
- [Rackspace CloudFiles](http://www.rackspace.com/cloud/files) (WIP)
|
158
|
+
- [Google Cloud Storage](https://developers.google.com/storage) (WIP)
|
115
159
|
|
116
160
|
## Supported Ruby Versions
|
117
161
|
|
data/lib/multi_sync/client.rb
CHANGED
@@ -2,32 +2,32 @@ require 'set'
|
|
2
2
|
require 'virtus'
|
3
3
|
require 'lazily'
|
4
4
|
require 'celluloid'
|
5
|
-
|
6
|
-
require
|
7
|
-
|
8
|
-
require 'multi_sync/targets/local_target'
|
5
|
+
%w(sources targets).each do |dir|
|
6
|
+
Dir.glob(File.expand_path("../#{dir}/**/*.rb", __FILE__), &method(:require))
|
7
|
+
end
|
9
8
|
require 'multi_sync/mixins/pluralize_helper'
|
10
9
|
|
11
10
|
module MultiSync
|
12
11
|
class Client
|
13
|
-
include Virtus
|
12
|
+
include Virtus.model
|
14
13
|
include MultiSync::Mixins::PluralizeHelper
|
15
14
|
|
16
|
-
attribute :supervisor
|
15
|
+
attribute :supervisor, Celluloid::SupervisionGroup
|
17
16
|
attribute :incomplete_jobs, Set, default: Set.new
|
18
17
|
attribute :running_jobs, Set, default: Set.new
|
19
18
|
attribute :complete_jobs, Set, default: Set.new
|
20
19
|
attribute :sources, Array, default: []
|
21
20
|
attribute :sync_attempts, Integer, default: 0
|
22
21
|
attribute :file_sync_attempts, Integer, default: 0
|
23
|
-
attribute :started_at, Time
|
24
|
-
attribute :finished_at, Time
|
22
|
+
attribute :started_at, Time, required: false
|
23
|
+
attribute :finished_at, Time, required: false
|
25
24
|
|
26
25
|
# Initialize a new Client object
|
27
26
|
#
|
28
27
|
# @param options [Hash]
|
29
|
-
def initialize(
|
28
|
+
def initialize(*args)
|
30
29
|
self.supervisor = Celluloid::SupervisionGroup.run!
|
30
|
+
super
|
31
31
|
end
|
32
32
|
|
33
33
|
def add_target(name, options = {})
|
@@ -50,12 +50,8 @@ module MultiSync
|
|
50
50
|
alias_method :source, :add_source
|
51
51
|
|
52
52
|
def synchronize
|
53
|
-
if sync_pointless?
|
54
|
-
|
55
|
-
return
|
56
|
-
else
|
57
|
-
MultiSync.debug 'Starting synchronization...'
|
58
|
-
end
|
53
|
+
MultiSync.debug 'Preventing synchronization as there are no sources found.' && return if sync_pointless?
|
54
|
+
MultiSync.debug 'Starting synchronization...'
|
59
55
|
|
60
56
|
determine_sync if first_run?
|
61
57
|
sync_attempted
|
@@ -69,8 +65,9 @@ module MultiSync
|
|
69
65
|
running_jobs.delete_if do | job |
|
70
66
|
begin
|
71
67
|
completed_job = { id: job[:id], response: job[:future].value, method: job[:method] }
|
72
|
-
rescue
|
68
|
+
rescue => error
|
73
69
|
self.file_sync_attempts = file_sync_attempts + 1
|
70
|
+
MultiSync.warn error.inspect
|
74
71
|
false
|
75
72
|
else
|
76
73
|
complete_jobs << completed_job
|
@@ -84,18 +81,23 @@ module MultiSync
|
|
84
81
|
alias_method :sync, :synchronize
|
85
82
|
|
86
83
|
def finalize
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
84
|
+
if finished_at
|
85
|
+
elapsed = finished_at.to_f - started_at.to_f
|
86
|
+
minutes, seconds = elapsed.divmod 60.0
|
87
|
+
bytes = get_total_file_size_from_complete_jobs
|
88
|
+
MultiSync.debug "Sync completed in #{pluralize(minutes.round, 'minute')} and #{pluralize(seconds.round, 'second')}"
|
89
|
+
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')}"
|
90
|
+
if bytes > 1024.0
|
91
|
+
kilobytes = bytes / 1024.0
|
92
|
+
MultiSync.debug "The upload weight totalled %.#{0}f #{pluralize(kilobytes, 'kilobyte', nil, false)}" % kilobytes
|
93
|
+
else
|
94
|
+
MultiSync.debug "The upload weight totalled %.#{0}f #{pluralize(bytes, 'byte', nil, false)}" % bytes
|
95
|
+
end
|
96
|
+
MultiSync.debug "#{pluralize(file_sync_attempts, 'failed request')} were detected and re-tried"
|
97
|
+
else
|
98
|
+
MultiSync.debug "Sync failed to complete with #{pluralize(incomplete_jobs.length, 'outstanding file')} to be synchronised"
|
99
|
+
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')}"
|
100
|
+
end
|
99
101
|
|
100
102
|
supervisor.finalize
|
101
103
|
end
|
@@ -112,12 +114,8 @@ module MultiSync
|
|
112
114
|
def get_total_file_size_from_complete_jobs
|
113
115
|
total_file_size = 0
|
114
116
|
get_complete_upload_jobs.each do | job |
|
115
|
-
|
116
|
-
|
117
|
-
if job[:response].content_length
|
118
|
-
total_file_size += job[:response].content_length
|
119
|
-
end
|
120
|
-
|
117
|
+
job_content_length = job[:response].content_length || job[:response].determine_content_length || 0
|
118
|
+
total_file_size += job_content_length
|
121
119
|
end
|
122
120
|
total_file_size
|
123
121
|
end
|
@@ -164,8 +162,8 @@ module MultiSync
|
|
164
162
|
abandoned_files_msg += ", however we're skipping them as :delete_abandoned_files is false" unless MultiSync.delete_abandoned_files
|
165
163
|
MultiSync.debug abandoned_files_msg
|
166
164
|
|
167
|
-
# remove missing_files from source_files (
|
168
|
-
# remove abandoned_files from target_files (
|
165
|
+
# remove missing_files from source_files (as we know they are missing so don't need to check them)
|
166
|
+
# remove abandoned_files from target_files (as we know they are abandoned so don't need to check them)
|
169
167
|
outdated_files.concat determine_outdated_files(source_files - missing_files, target_files - abandoned_files)
|
170
168
|
MultiSync.debug "#{outdated_files.length} of the files are outdated"
|
171
169
|
|
@@ -4,7 +4,7 @@ require 'celluloid'
|
|
4
4
|
|
5
5
|
module MultiSync
|
6
6
|
class Configuration
|
7
|
-
include Virtus
|
7
|
+
include Virtus.model
|
8
8
|
|
9
9
|
attribute :verbose, Boolean, default: false
|
10
10
|
attribute :force, Boolean, default: false
|
@@ -18,11 +18,9 @@ module MultiSync
|
|
18
18
|
# Initialize a new Configuration object
|
19
19
|
#
|
20
20
|
# @param options [Hash]
|
21
|
-
def initialize(
|
21
|
+
def initialize(*args)
|
22
22
|
Celluloid.logger = MultiSync.test? ? nil : MultiSync.logger
|
23
|
-
|
24
|
-
send("#{key}=", value) if attributes.keys.include?(key)
|
25
|
-
end
|
23
|
+
super
|
26
24
|
end
|
27
25
|
|
28
26
|
def celluloid_cores
|
@@ -16,8 +16,6 @@ module MultiSync
|
|
16
16
|
|
17
17
|
def check_and_migrate
|
18
18
|
return unless self.asset_sync_yml_exists?
|
19
|
-
MultiSync.info 'AssetSync YAML file found, migrating options...'
|
20
|
-
|
21
19
|
MultiSync.source(:rails,
|
22
20
|
type: :manifest,
|
23
21
|
source_dir: MultiSync::Extensions::Rails.source_dir
|
@@ -37,6 +35,8 @@ module MultiSync
|
|
37
35
|
|
38
36
|
MultiSync.delete_abandoned_files = asset_sync_yml['existing_remote_files'] == 'delete'
|
39
37
|
MultiSync.run_on_build = asset_sync_yml['run_on_precompile']
|
38
|
+
|
39
|
+
MultiSync.info 'AssetSync YAML file found, migrating options...' if MultiSync.run_on_build
|
40
40
|
end
|
41
41
|
end
|
42
42
|
end
|
data/lib/multi_sync/logging.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'logger'
|
2
|
+
require 'thread'
|
2
3
|
|
3
4
|
module MultiSync
|
4
5
|
module Logging
|
@@ -31,9 +32,8 @@ module MultiSync
|
|
31
32
|
end
|
32
33
|
|
33
34
|
def log(message, level = :debug)
|
34
|
-
# We're in verbose mode so disable all non-info logs
|
35
|
+
# We're not in verbose mode so disable all non-info logs
|
35
36
|
return if !MultiSync.verbose && level != :info
|
36
|
-
|
37
37
|
MUTEX.synchronize do
|
38
38
|
logger.send(level, message)
|
39
39
|
end
|
data/lib/multi_sync/resource.rb
CHANGED
@@ -5,63 +5,46 @@ require 'multi_sync/mixins/log_helper'
|
|
5
5
|
|
6
6
|
module MultiSync
|
7
7
|
class Resource
|
8
|
-
include Virtus
|
9
8
|
include Comparable
|
9
|
+
include Virtus.model
|
10
10
|
include MultiSync::Mixins::LogHelper
|
11
11
|
|
12
|
-
attribute :file, File
|
13
12
|
attribute :path_with_root, Pathname
|
14
13
|
attribute :path_without_root, Pathname
|
15
14
|
|
16
|
-
attribute :etag, String
|
17
|
-
attribute :mtime, Time
|
18
|
-
attribute :content_length, Numeric
|
19
|
-
attribute :content_type, String
|
20
|
-
attribute :digest, String
|
15
|
+
attribute :etag, String, default: :determine_etag, lazy: true
|
16
|
+
attribute :mtime, Time, default: :determine_mtime, lazy: true
|
17
|
+
attribute :content_length, Numeric, default: :determine_content_length, lazy: true
|
18
|
+
attribute :content_type, String, default: :determine_content_type, lazy: true
|
19
|
+
attribute :digest, String, default: ''
|
21
20
|
|
22
21
|
AWS_ATTRIBUTES = [{
|
23
22
|
name: :storage_class,
|
24
23
|
type: String,
|
25
|
-
|
24
|
+
default: 'STANDARD'
|
26
25
|
}, {
|
27
26
|
name: :acl,
|
28
27
|
type: String,
|
29
|
-
|
28
|
+
default: 'public-read'
|
30
29
|
}, {
|
31
30
|
name: :expires,
|
32
31
|
type: String,
|
33
|
-
|
32
|
+
required: false
|
34
33
|
}, {
|
35
34
|
name: :cache_control,
|
36
35
|
type: String,
|
37
|
-
|
36
|
+
required: false
|
38
37
|
}, {
|
39
38
|
name: :encryption,
|
40
39
|
type: String,
|
41
|
-
|
40
|
+
required: false
|
42
41
|
}]
|
43
42
|
|
44
43
|
AWS_ATTRIBUTES.each do |attribute_hash|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
#
|
50
|
-
# @param options [Hash]
|
51
|
-
def initialize(options = {})
|
52
|
-
fail(ArgumentError, 'with_root must be present') unless options[:with_root]
|
53
|
-
fail(ArgumentError, 'without_root must be present') unless options[:without_root]
|
54
|
-
self.path_with_root = options.fetch(:with_root)
|
55
|
-
self.path_without_root = options.fetch(:without_root)
|
56
|
-
self.etag = options.fetch(:etag, determine_etag)
|
57
|
-
self.mtime = options.fetch(:mtime, determine_mtime)
|
58
|
-
self.content_length = options.fetch(:content_length, determine_content_length)
|
59
|
-
self.content_type = options.fetch(:content_type, determine_content_type)
|
60
|
-
self.digest = options.fetch(:digest, '')
|
61
|
-
|
62
|
-
AWS_ATTRIBUTES.each do |attribute_hash|
|
63
|
-
send("#{attribute_hash[:name]}=".to_sym, options.fetch(attribute_hash[:name], attribute_hash[:default_value]))
|
64
|
-
end
|
44
|
+
def_attribute_hash = {}
|
45
|
+
def_attribute_hash[:default] = attribute_hash[:default] unless attribute_hash[:default].nil?
|
46
|
+
def_attribute_hash[:required] = attribute_hash[:required] unless attribute_hash[:required].nil?
|
47
|
+
send(:attribute, attribute_hash[:name], attribute_hash[:type], def_attribute_hash)
|
65
48
|
end
|
66
49
|
|
67
50
|
def hash
|
data/lib/multi_sync/source.rb
CHANGED
@@ -1,40 +1,28 @@
|
|
1
1
|
require 'virtus'
|
2
2
|
require 'pathname'
|
3
3
|
require 'lazily'
|
4
|
+
require 'multi_sync/attributes/pathname'
|
4
5
|
require 'multi_sync/mixins/log_helper'
|
6
|
+
require 'multi_sync/resources/local_resource'
|
5
7
|
|
6
8
|
module MultiSync
|
7
9
|
class Source
|
8
|
-
include Virtus
|
10
|
+
include Virtus.model
|
9
11
|
include MultiSync::Mixins::LogHelper
|
10
12
|
|
11
|
-
attribute :
|
12
|
-
attribute :source_dir, String
|
13
|
-
attribute :source_options, Hash
|
14
|
-
attribute :include, String
|
15
|
-
attribute :exclude, String
|
13
|
+
attribute :source_dir, MultiSync::Attributes::Pathname
|
16
14
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
fail(ArgumentError, 'source_dir must be a present') unless options[:source_dir]
|
22
|
-
targets.concat([*options.fetch(:targets, [])])
|
23
|
-
self.source_dir = options.fetch(:source_dir).to_s
|
24
|
-
source_dir << '/' unless source_dir.end_with?('/')
|
25
|
-
self.source_dir = Pathname.new(source_dir)
|
26
|
-
self.include = options.fetch(:include, '**/*')
|
27
|
-
self.exclude = options.fetch(:exclude, nil)
|
28
|
-
end
|
15
|
+
attribute :targets, Array, default: []
|
16
|
+
attribute :resource_options, Hash, default: {}
|
17
|
+
attribute :include, String, default: '**/*'
|
18
|
+
attribute :exclude, String, default: ''
|
29
19
|
|
30
20
|
private
|
31
21
|
|
32
22
|
def path_to_local_resource(path, options = {})
|
33
23
|
pathname = Pathname.new(path)
|
34
|
-
|
35
|
-
|
36
|
-
without_root: pathname.relative_path_from(source_dir).cleanpath
|
37
|
-
}.merge(options).merge(source_options))
|
24
|
+
path_options = { path_with_root: pathname, path_without_root: pathname.relative_path_from(source_dir).cleanpath }
|
25
|
+
MultiSync::LocalResource.new(path_options.merge(options).merge(resource_options))
|
38
26
|
end
|
39
27
|
end
|
40
28
|
end
|
@@ -22,7 +22,7 @@ module MultiSync
|
|
22
22
|
# making sure to skip any that do not match the include/exclude patterns
|
23
23
|
manifest_hash.lazily.each { |key, value|
|
24
24
|
path = source_dir + key
|
25
|
-
next if !path.fnmatch?(include.to_s)
|
25
|
+
next if !path.fnmatch?(include.to_s) || path.fnmatch?(exclude.to_s || '')
|
26
26
|
file = path_to_local_resource(path, mtime: value['mtime'], digest: value['digest'], content_length: value['size'])
|
27
27
|
files << file
|
28
28
|
}
|
@@ -33,7 +33,7 @@ module MultiSync
|
|
33
33
|
private
|
34
34
|
|
35
35
|
def locate_manifest(dir)
|
36
|
-
Dir.glob(dir
|
36
|
+
Dir.glob(dir + 'manifest*.{json,yaml,yml}').max { |f| File.ctime(f) }
|
37
37
|
end
|
38
38
|
|
39
39
|
def parse_manifest(manifest_path)
|