vidibus-resource 0.2.1 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile CHANGED
@@ -1,25 +1,25 @@
1
- require "bundler"
2
- require "rdoc/task"
3
- require "rspec"
4
- require "rspec/core/rake_task"
1
+ $:.unshift File.expand_path('../lib', __FILE__)
5
2
 
6
- Bundler::GemHelper.install_tasks
3
+ require 'bundler'
4
+ require 'rdoc/task'
5
+ require 'rspec'
6
+ require 'rspec/core/rake_task'
7
+ require 'vidibus/resource/version'
7
8
 
8
- $LOAD_PATH.unshift File.expand_path("../lib", __FILE__)
9
- require "vidibus/resource/version"
9
+ Bundler::GemHelper.install_tasks
10
10
 
11
11
  RSpec::Core::RakeTask.new(:rcov) do |t|
12
- t.pattern = "spec/**/*_spec.rb"
12
+ t.pattern = 'spec/**/*_spec.rb'
13
13
  t.rcov = true
14
- t.rcov_opts = ["--exclude", "^spec,/gems/"]
14
+ t.rcov_opts = ['--exclude', '^spec,/gems/']
15
15
  end
16
16
 
17
17
  Rake::RDocTask.new do |rdoc|
18
- rdoc.rdoc_dir = "rdoc"
18
+ rdoc.rdoc_dir = 'rdoc'
19
19
  rdoc.title = "vidibus-sysinfo #{Vidibus::Resource::VERSION}"
20
- rdoc.rdoc_files.include("README*")
21
- rdoc.rdoc_files.include("lib/**/*.rb")
22
- rdoc.options << "--charset=utf-8"
20
+ rdoc.rdoc_files.include('README*')
21
+ rdoc.rdoc_files.include('lib/**/*.rb')
22
+ rdoc.options << '--charset=utf-8'
23
23
  end
24
24
 
25
25
  task :default => :rcov
@@ -1,51 +1,88 @@
1
- # TODO: Split this file: one part for providers, one for consumers?
1
+ # TODO: Split this file: one part for providers, one for consumers!
2
2
  class Api::ResourcesController < ApiController
3
3
  before_filter :ensure_klass
4
- before_filter :find_instance
4
+ before_filter :ensure_instance, :unless => :no_instance_required?
5
5
 
6
- # Creates resource consumer on provider.
6
+ # Creates resource consumer on provider or consumer.
7
+ # This action does not care if a resource already exists on consumer.
7
8
  def create
8
- @instance.add_resource_consumer(params["service"])
9
- render(:json => {:resource => JSON.generate(@instance.resourceable_hash)})
9
+ if provider?
10
+ instance.add_resource_consumer(params[:service], params[:realm])
11
+ render(:json => {:resource => JSON.generate(instance.resourceable_hash)})
12
+ else
13
+ if instance
14
+ instance.update_resource_attributes(params[:resource])
15
+ else
16
+ attributes = {:uuid => params[:uuid], :resource_attributes => JSON.parse(params[:resource])}
17
+ attributes[:realm_uuid] = params[:realm] if klass_with_realm?
18
+ klass.create!(attributes)
19
+ end
20
+ render(:nothing => true)
21
+ end
10
22
  end
11
23
 
12
24
  # Updates resource on consumer.
13
25
  def update
14
26
  begin
15
- @instance.update_resource_attributes(params["resource"])
27
+ instance.update_resource_attributes(params['resource'])
16
28
  render :nothing => true
17
29
  rescue => e
18
- Rails.logger.error 'Error while updating resource consumer: '+e.inspect
30
+ Rails.logger.error "Error while updating resource consumer:\n#{e.inspect}"
19
31
  render(:json => {:error => e}, :status => :bad_request)
20
32
  end
21
33
  end
22
34
 
23
- # Removes a resource consumer from provider
24
- # or remove a resource from a consumer.
35
+ # Removes a resource consumer from provider or consumer.
25
36
  def destroy
26
- if @instance.respond_to?(:resource_consumers)
27
- @instance.remove_resource_consumer(params["service"])
37
+ if provider?
38
+ instance.remove_resource_consumer(params[:service], params[:realm])
28
39
  else
29
- @instance.destroy_without_callback
40
+ instance.destroy_without_callback
30
41
  end
31
- render :nothing => true
42
+ render(:nothing => true)
32
43
  end
33
44
 
34
45
  private
35
46
 
36
- def ensure_klass
37
- begin
38
- @klass = params[:klass].classify.constantize
47
+ def klass
48
+ @klass ||= begin
49
+ params[:klass].classify.constantize
39
50
  rescue => e
40
- render :json => {:error => e}, :status => :bad_request
51
+ @klass_error = e
52
+ end
53
+ end
54
+
55
+ def klass_with_realm?
56
+ @is_klass_with_realm ||= klass.instance_methods.include?('realm_uuid')
57
+ end
58
+
59
+ def instance
60
+ @instance ||= begin
61
+ results = klass.where(:uuid => params[:uuid])
62
+ if klass_with_realm?
63
+ results = results.and(:realm_uuid => params[:realm])
64
+ end
65
+ results.first
41
66
  end
42
67
  end
43
68
 
44
- def find_instance
45
- result = @klass.where(:uuid => params[:uuid])
46
- if @klass.new.respond_to?(:realm_uuid)
47
- result.and(:realm_uuid => params[:realm])
69
+ def no_instance_required?
70
+ %w[create].include?(action_name) and !provider?
71
+ end
72
+
73
+ def ensure_klass
74
+ if !klass or @klass_error
75
+ render(:json => {:error => @klass_error}, :status => :bad_request)
76
+ end
77
+ end
78
+
79
+ def provider?
80
+ @is_provider ||= klass.instance_methods.include?('resource_consumers')
81
+ end
82
+
83
+ def ensure_instance
84
+ unless instance
85
+ render(:json => {:error => "#{klass} #{params[:uuid]} not found"}, :status => :not_found)
48
86
  end
49
- @instance = result.first or render(:json => {:error => "#{@klass} #{params[:uuid]} not found"}, :status => :not_found)
50
87
  end
51
88
  end
@@ -1,14 +1,12 @@
1
1
  module Vidibus::Resource
2
2
  module Consumer
3
-
4
- class ConfigurationError < StandardError; end
3
+ class ConsumerError < Error; end
4
+ class ConfigurationError < ConsumerError; end
5
5
 
6
6
  module Mongoid
7
7
  extend ActiveSupport::Concern
8
8
 
9
9
  included do
10
- include Vidibus::Uuid::Mongoid
11
-
12
10
  field :resource_attributes, :type => Hash, :default => {}
13
11
  field :uuid
14
12
  index :uuid
@@ -16,7 +14,7 @@ module Vidibus::Resource
16
14
 
17
15
  attr_accessor :extinct
18
16
 
19
- before_create :add_resource_consumer
17
+ before_create :add_resource_consumer, :unless => :resource_attributes?
20
18
  before_save :set_resource_attributes
21
19
  before_destroy :remove_resource_consumer, :unless => :extinct
22
20
  end
@@ -24,38 +22,72 @@ module Vidibus::Resource
24
22
  # Registers this consumer with provider.
25
23
  def add_resource_consumer
26
24
  response = register_resource_consumer
27
- self.resource_attributes = JSON.parse(response["resource"])
25
+ self.resource_attributes = JSON.parse(response['resource'])
28
26
  set_resource_attributes(true)
29
27
  true # ensure true!
30
28
  end
31
29
 
32
30
  # Removes this consumer from provider.
33
31
  def remove_resource_consumer
34
- resource_provider.delete("/api/resources/#{self.class.to_s.tableize}/#{uuid}")
32
+ resource_provider.delete(resource_uri)
35
33
  true # ensure true!
36
34
  end
37
35
 
38
- # Updates resource attributes.
36
+ # Updates resource attributes from given JSON data.
39
37
  # TODO: Update only data that has been changed.
40
- def update_resource_attributes(data)
41
- update_attributes(:resource_attributes => JSON.parse(data))
38
+ def update_resource_attributes(json)
39
+ update_attributes(:resource_attributes => JSON.parse(json))
42
40
  end
43
41
 
44
42
  # Returns a resource provider service.
45
43
  def resource_provider
46
44
  @resource_provider ||= begin
47
- service = self.class.instance_variable_get("@resource_provider") or
45
+ service = self.class.instance_variable_get('@resource_provider') or
48
46
  raise ConfigurationError.new("No resource provider has been defined. Call #{self.class}.resource_provider(service, realm)")
49
- realm = (self.class.instance_variable_get("@resource_realm") || try!(:realm_uuid)) or
50
- raise ConfigurationError.new("No resource realm has been defined. Call #{self.class}.resource_realm(realm)")
47
+ realm = (self.class.instance_variable_get('@resource_realm') || try!(:realm_uuid)) or
48
+ raise ConfigurationError.new("No resource realm has been defined. Call #{self.class}.resource_realm(realm) or define the attribute :realm_uuid.")
51
49
  ::Service.discover(service, realm)
52
50
  end
53
51
  end
54
52
 
55
- # Populates attributes of instance from
56
- # received resource_attributes hash.
53
+ def destroy_without_callback
54
+ self.extinct = true
55
+ destroy
56
+ end
57
+
58
+ module ClassMethods
59
+
60
+ # Sets up resource provider service type and realm.
61
+ def resource_provider(service, realm = nil)
62
+ @resource_provider = service
63
+ resource_realm(realm) if realm
64
+ end
65
+
66
+ # Sets up realm of resource.
67
+ # If no realm has been set up class-wide, the attribute :realm_uuid will be used.
68
+ def resource_realm(realm)
69
+ @resource_realm = realm
70
+ end
71
+
72
+ # Ensures that an instance with given conditions exists.
73
+ def ensure!(conditions)
74
+ self.where(conditions).first || self.create!(conditions)
75
+ end
76
+
77
+ # Remove all intances with given conditions.
78
+ def remove(conditions)
79
+ existing = self.where(conditions).to_a
80
+ for instance in existing
81
+ instance.destroy
82
+ end
83
+ end
84
+ end
85
+
86
+ private
87
+
88
+ # Populates attributes of instance from resource_attributes hash.
57
89
  def set_resource_attributes(force = false)
58
- if resource_attributes_changed? or force == true
90
+ if resource_attributes_changed? or new_record? or force == true
59
91
  for key, value in resource_attributes
60
92
  meth = key.to_s
61
93
 
@@ -90,42 +122,12 @@ module Vidibus::Resource
90
122
  true # ensure true!
91
123
  end
92
124
 
93
- def destroy_without_callback
94
- self.extinct = true
95
- destroy
96
- end
97
-
98
- private
99
-
100
125
  def register_resource_consumer
101
- resource_provider.post("/api/resources/#{self.class.to_s.tableize}/#{uuid}")
126
+ resource_provider.post(resource_uri)
102
127
  end
103
128
 
104
- module ClassMethods
105
-
106
- # Sets up resource provider service type and realm.
107
- def resource_provider(service, realm = nil)
108
- @resource_provider = service
109
- resource_realm(realm) if realm
110
- end
111
-
112
- # Sets up realm of resource.
113
- def resource_realm(realm)
114
- @resource_realm = realm
115
- end
116
-
117
- # Ensures that an instance with given conditions exists.
118
- def ensure!(conditions)
119
- self.where(conditions).first || self.create!(conditions)
120
- end
121
-
122
- # Remove all intances with given conditions.
123
- def remove(conditions)
124
- existing = self.where(conditions).to_a
125
- for instance in existing
126
- instance.destroy
127
- end
128
- end
129
+ def resource_uri
130
+ @resource_uri ||= "/api/resources/#{self.class.to_s.tableize}/#{uuid}"
129
131
  end
130
132
  end
131
133
  end
@@ -1,67 +1,90 @@
1
- require "digest/md5"
1
+ require 'digest/md5'
2
2
 
3
3
  module Vidibus::Resource
4
4
  module Provider
5
+ class ProviderError < Error; end
6
+ class ServiceError < ProviderError; end
7
+ class ConsumerNotFoundError < ProviderError; end
8
+
5
9
  module Mongoid
6
10
  extend ActiveSupport::Concern
7
11
 
8
12
  included do
9
- field :resource_consumers, :type => Array, :default => []
13
+ field :resource_consumers, :type => Hash, :default => {}
10
14
  field :resourceable_hash_checksum, :type => Hash
11
15
 
12
16
  before_update :update_resource_consumers
13
17
  before_destroy :destroy_resource_consumers
18
+
19
+ scope :consumers_in_realm, lambda {|realm| where("resource_consumers.#{realm_uuid}" => {'$exists' => true})}
14
20
  end
15
21
 
16
22
  # Adds given resource consumer.
17
- def add_resource_consumer(service_uuid)
18
- list = resource_consumers || []
19
- unless list.include?(service_uuid)
20
- list << service_uuid
21
- update_attributes(:resource_consumers => list.uniq)
23
+ def add_resource_consumer(service_uuid, realm_uuid)
24
+ self.resource_consumers ||= {}
25
+ self.resource_consumers[realm_uuid] ||= []
26
+ unless resource_consumers[realm_uuid].include?(service_uuid)
27
+ self.resource_consumers[realm_uuid] << service_uuid
28
+ create_resource_consumer(service_uuid, realm_uuid)
29
+ save
22
30
  end
23
31
  end
24
32
 
25
33
  # Removes given resource consumer.
26
- def remove_resource_consumer(service_uuid)
27
- self.resource_consumers.delete(service_uuid)
34
+ def remove_resource_consumer(service_uuid, realm_uuid)
35
+ unless resource_consumers[realm_uuid] and resource_consumers[realm_uuid].include?(service_uuid)
36
+ raise(ConsumerNotFoundError, "This resource has no consumer #{service_uuid} within realm #{realm_uuid}.")
37
+ end
38
+ destroy_resource_consumer(service_uuid, realm_uuid)
39
+ self.resource_consumers[realm_uuid].delete(service_uuid)
40
+ self.resource_consumers.delete(realm_uuid) if resource_consumers[realm_uuid].blank?
28
41
  save
29
42
  end
30
43
 
44
+ # TODO: Get rid of this! It's only for the controller...
31
45
  def resource_provider?
32
46
  true
33
47
  end
34
48
 
49
+ # TODO: Get rid of this! It's only for the controller...
35
50
  def resource_consumer?
36
51
  false
37
52
  end
38
53
 
39
- # TODO: Handle attributes properly
40
54
  def resourceable_hash
41
- attributes
55
+ @resourceable_hash ||= attributes.except('resource_consumers', '_id')
56
+ end
57
+
58
+ def resourceable_hash_json
59
+ @resourceable_hash_json ||= JSON.generate(resourceable_hash)
42
60
  end
43
61
 
44
62
  private
45
63
 
46
- # Update resource consumers if significant changes were made.
64
+ def resource_uri
65
+ @resource_uri ||= "/api/resources/#{self.class.to_s.tableize}/#{uuid}"
66
+ end
67
+
68
+ # Performs given block on each resource consumer service.
69
+ def each_resource_consumer
70
+ resource_consumers.each do |realm_uuid, service_uuids|
71
+ service_uuids.each do |service_uuid|
72
+ yield(service_uuid, realm_uuid)
73
+ end
74
+ end
75
+ end
76
+
77
+ # Updates resource consumers if significant changes were made.
47
78
  # TODO: Send changes only (the resourceable ones)!
48
79
  # Performs update asynchronously.
49
80
  def update_resource_consumers
50
81
  return unless resource_consumers and resource_consumers.any?
51
- return unless changes.except("resource_consumers", "updated_at").any?
52
-
53
- hash = resourceable_hash
54
- hash_checksum = Digest::MD5.hexdigest(hash.to_s)
55
- unless hash_checksum == resourceable_hash_checksum
56
- self.resourceable_hash_checksum = hash_checksum
57
- uri = "/api/resources/#{self.class.to_s.tableize}/#{uuid}"
58
- for service in resource_consumers
59
- begin
60
- ::Service.discover(service, realm_uuid).delay.put(uri, :body => {:resource => JSON.generate(hash)})
61
- rescue => e
62
- Rails.logger.error "An error occurred while updating resource consumer #{service}:"
63
- Rails.logger.error e.inspect
64
- end
82
+ return unless changes.except('resource_consumers', 'updated_at').any?
83
+
84
+ self.resourceable_hash_checksum = Digest::MD5.hexdigest(resourceable_hash_json)
85
+ if resourceable_hash_checksum_changed?
86
+ each_resource_consumer do |service_uuid, realm_uuid|
87
+ update_resource_consumer(service_uuid, realm_uuid)
65
88
  end
66
89
  end
67
90
  end
@@ -69,16 +92,32 @@ module Vidibus::Resource
69
92
  # Removes this resource from consumers.
70
93
  # Performs update asynchronously.
71
94
  def destroy_resource_consumers
72
- for service in resource_consumers
73
- begin
74
- ::Service.discover(service, realm_uuid).delay.delete("/api/resources/#{self.class.to_s.tableize}/#{uuid}")
75
- rescue => e
76
- Rails.logger.error "An error occurred while destroying resource consumer #{service}:"
77
- Rails.logger.error e.inspect
78
- errors = true
79
- end
95
+ each_resource_consumer do |service_uuid, realm_uuid|
96
+ destroy_resource_consumer(service_uuid, realm_uuid)
97
+ end
98
+ end
99
+
100
+ # Sends an API request to create the resource consumer.
101
+ def create_resource_consumer(service_uuid, realm_uuid)
102
+ resource_consumer_request(service_uuid, realm_uuid, :post, :body => {:resource => resourceable_hash_json})
103
+ end
104
+
105
+ # Sends an API request to update the resource consumer.
106
+ def update_resource_consumer(service_uuid, realm_uuid)
107
+ resource_consumer_request(service_uuid, realm_uuid, :put, :body => {:resource => resourceable_hash_json})
108
+ end
109
+
110
+ # Sends an API request to delete the resource consumer.
111
+ def destroy_resource_consumer(service_uuid, realm_uuid)
112
+ resource_consumer_request(service_uuid, realm_uuid, :delete)
113
+ end
114
+
115
+ def resource_consumer_request(service_uuid, realm_uuid, method, options = {})
116
+ begin
117
+ ::Service.discover(service_uuid, realm_uuid).delay.send(method, resource_uri, options)
118
+ rescue => e
119
+ raise(ServiceError, "Sending a #{method} request to the resource consumer #{service_uuid} within realm #{realm_uuid} failed!\n#{e.inspect}")
80
120
  end
81
- true unless errors # ensure true!
82
121
  end
83
122
  end
84
123
  end
@@ -1,5 +1,5 @@
1
1
  module Vidibus
2
2
  module Resource
3
- VERSION = "0.2.1"
3
+ VERSION = "0.3.1"
4
4
  end
5
5
  end
@@ -1,2 +1,8 @@
1
+ module Vidibus
2
+ module Resource
3
+ class Error < StandardError; end
4
+ end
5
+ end
6
+
1
7
  require "vidibus/resource/provider/mongoid"
2
8
  require "vidibus/resource/consumer/mongoid"
@@ -1,8 +1,11 @@
1
1
  require "json"
2
2
  require "rails"
3
+ require "delayed_job"
4
+ require "delayed_job_mongoid"
3
5
  require "vidibus-uuid"
4
6
  require "vidibus-secure"
5
7
  require "vidibus-api"
8
+ require "vidibus-service"
6
9
 
7
10
  require "vidibus/resource"
8
11
 
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vidibus-resource
3
3
  version: !ruby/object:Gem::Version
4
- hash: 21
4
+ hash: 17
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
- - 2
8
+ - 3
9
9
  - 1
10
- version: 0.2.1
10
+ version: 0.3.1
11
11
  platform: ruby
12
12
  authors:
13
13
  - Andre Pankratz
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-07-14 00:00:00 +02:00
18
+ date: 2011-09-13 00:00:00 +02:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency