vidibus-resource 0.2.1 → 0.3.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.
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