multi_sync 0.0.1 → 0.0.2
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/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]
|
|
@@ -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)
|