Class: Smash::CloudPowers::Context

Inherits:
Object
  • Object
show all
Includes:
Helper
Defined in:
lib/cloud_powers/context.rb

Overview

The Context class is the class that handles serializing the Context so that it can be passed from node to node and rebuilt. This provides a way for nodes in the same Brain to have an awareness of required communication modes, for example. Because resources generally require some sort of information to connect with or create and a Brain operates in the same Context, it can use the Context to decouple the creation and usage from the coordination.

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Helper

#attr_map!, #available_resources, #called_from, #create_logger, #deep_modify_keys_with, #format_error_message, #log_file, #logger, #modify_keys_with, #smart_retry, #task_exist?, #task_home, #task_path, #task_require_path, #to_camel, #to_hyph, #to_i_var, #to_pascal, #to_ruby_file_name, #to_snake, #update_message_body, #valid_json?, #valid_url?

Constructor Details

#initialize(args) ⇒ Context

Attempts to create a Context out of the argument(s) you've passed.

Parameters

  • args +Hash+|+JSON+|+Array+|+Enumerable+
    • expample Hash:
      • each key is a module or class that is in CloudPowers and each value is either an array of configurations information or a single configuration. { task: 'demo', queue: [:backlog, :sned], pipe: :status_stream }
    • expample Array
      • each key is followed by 0..n valid configurations information [:task, 'demo', :queue, :backlog, :sned, :pipe, :status_stream]

Returns Smash::Context



32
33
34
35
36
37
38
39
# File 'lib/cloud_powers/context.rb', line 32

def initialize(args)
  unless valid_args?(args)
    raise ArgumentError.new 'Can be either a Hash, JSON, or an Enumerable ' +
      "arguments: #{args}"
  end
  @package = args
  @structure = decipher(args)
end

Instance Attribute Details

#package ⇒ Object

The given data structure that is used to build @structure



15
16
17
# File 'lib/cloud_powers/context.rb', line 15

def package
  @package
end

Instance Method Details

#decipher(args) ⇒ Object

Decipher figures out which translation method to use by making some simple type checks, etc. and then routing the args to the correct method.

Notes

  • See #translate_json()
  • See #translate_list()


47
48
49
50
51
52
53
54
55
56
# File 'lib/cloud_powers/context.rb', line 47

def decipher(args)
  case args
  when Hash
    args
  when String
    translate_json(args)
  when Enumerable
    translate_list(args)
  end
end

#flatten ⇒ Object

Creates a flat Array of the 2-D Array that gets returned from #simplify()

Returns Array

Example example_context.structure

=> { task: 'demo', queue: [:backlog, :sned], pipe: [:status_stream] }

example.flatten

=> [:task, 'demo', :queue, :backlog, :sned, :pipe, :status_stream]

Notes

  • See +#simplify()
  • See #Array::flatten()


71
72
73
# File 'lib/cloud_powers/context.rb', line 71

def flatten
  simplify.flatten
end

#simplify ⇒ Object

Create an array version of @sructure by calling #to_a() on it

Returns Array

Example example_context.structure

=> { task: 'demo', queue: [:backlog, :sned], pipe: [:status_stream] }

example.simplify

=> [:task, 'demo', :queue, [:backlog, :sned], :pipe, [:status_stream]]

Notes

  • This uses the different Constants, like Smash, Synapse and anything it can find to decide what should be used as a key and what its following values array should contain. It basically says:
    1. if the nth item is a known key (from the above search), add it as an object in the Array.
    2. else, add it to the last sub-Array
    3. move to n+1 in the structure Hash
  • TODO: Check if this has a limit to n-layers


94
95
96
# File 'lib/cloud_powers/context.rb', line 94

def simplify
  @structure.to_a
end

#structure ⇒ Object

A Hash that represents the resources and some configuration for them

Returns Hash



101
102
103
# File 'lib/cloud_powers/context.rb', line 101

def structure
  modify_keys_with(@structure) { |key| key.to_sym }
end

#structure=(args) ⇒ Object

Valid scheme for @structure is assured by running the arguments through the decipher method, which is how @structure is set in #new(args)



107
108
109
# File 'lib/cloud_powers/context.rb', line 107

def structure=(args)
  @structure = decipher(args)
end

#to_json ⇒ Object

Uses #to_json() on the @structure Returns Hash



223
224
225
# File 'lib/cloud_powers/context.rb', line 223

def to_json
  structure.to_json
end

#translate_flattened(list) ⇒ Object

Translates an Array into a valid @structure Hash Parameters arr e.g. [:task, ['demo'], :queue, ['name1','name2',.,.,.,.,.], config hash,..., :pipe, ['name1'] Returns Hash Notes

  • calling #valid_hash_format?() on returned Hash will return true


179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
# File 'lib/cloud_powers/context.rb', line 179

def translate_flattened(list)
  arr = list.to_a
  results = []
  # get the indexes of CloudPowers resources in arr
  key_locations = arr.each_with_index.collect do |key, i, _|
    i if available_resources.include?(to_pascal(key).to_sym)
  end.reject(&:nil?)
  key_locations << arr.size # add the last index into the ranges
  # use each pair as ranges to slice up the Array
  key_locations.each_cons(2) do |current_i, next_i|
    results << [arr[current_i], arr[(current_i+1)..(next_i-1)]]
  end

  translate_simplified(results)
end

#translate_json(json_string) ⇒ Object

Parse the given JSON Parameters JSON Returns Hash



116
117
118
119
120
121
122
# File 'lib/cloud_powers/context.rb', line 116

def translate_json(json_string)
  begin
    JSON.parse(json_string)
  rescue JSON::ParserError
    raise ArgumentError "Incorrectly formatted JSON"
  end
end

#translate_list(list) ⇒ Object

Re-layer this flattened Array or enumerable list so that it looks like the Hash that it used to be before the Smash::Context#flatten() method was called

Parameters +Array+|+List+|+Enumerable+

Example

  • flat

    [
    object_name_1, config_1a, config_2a, ...,
    object_2, config_1b, etc,
    ...
    ]
    
  • or grouped

    [
    [object_name_1, config_1a, config_2a, ...],
    [object_2, config_1b, etc],
    ...
    ]
    
  • or structured

    [
    [object_name_1, [config_1a, config_2a, ...]],
    [object_2, [config_1b, etc]],
    ...
    ]
    
  • returns

    {
    object_1: [config_1a, config_2a, ...],
    object_2: [config_1b, ...],
    ...
    }
    

    Returns Hash

Notes If #valid_package_hash?() is called on this Hash, it will return true



167
168
169
# File 'lib/cloud_powers/context.rb', line 167

def translate_list(list)
  list.first.kind_of?(Enumerable) ? translate_simplified(list) : translate_flattened(list)
end

#translate_simplified(arr) ⇒ Object

Translates a 2D Array into a valid @structure Hash Parameters arr e.g.

  [
    [:task, 'demo'],
    [:queue, 'name1', {other config hash},...],
    [:pipe, 'name1']
    ...
  ]
  • Needs to be a 2D Array
  • First object of each inner-Array is the key
  • All following values in that inner Array are separate configuration information pieces that can be used in the #create!() method for that particular resource Returns Hash well formatted for the @structure


212
213
214
215
216
217
218
219
# File 'lib/cloud_powers/context.rb', line 212

def translate_simplified(arr)
  arr.inject({}) do |hash, key_config_map|
    hash.tap do |h|
      key = key_config_map.shift
      h[key.to_sym] = *key_config_map.flatten
    end
  end
end

#valid_args?(args) ⇒ Boolean

The Context class can be initialized in any of the formats that a Context class should exist in. It can be a vanilla version, where the @structure is a Hash, structured correctly or it can be serialized into JSON or it can be an Array Parameters args String Returns Boolean

Returns:

  • (Boolean)


233
234
235
236
237
238
239
240
241
242
243
244
# File 'lib/cloud_powers/context.rb', line 233

def valid_args?(args)
  case args
  when Hash
    valid_hash_format?(args)
  when String
    valid_json_format?(args)
  when Enumerable
    valid_array_format?(args)
  else
    false
  end
end

#valid_array_format?(list) ⇒ Boolean

Makes sure that the list is enumerable and that at least the first term is a resource name from Smash::CloudPowers. All other objects can potentially be configurations. Parameters list <Array|Enumerable> Returns Boolean

Returns:

  • (Boolean)


251
252
253
254
# File 'lib/cloud_powers/context.rb', line 251

def valid_array_format?(list)
  use = list.first.kind_of?(Enumerable) ? list.first.first : list.first
  ((list.kind_of? Enumerable) && (available_resources.include?(to_pascal(use).to_sym)))
end

#valid_hash_format?(hash) ⇒ Boolean

Makes sure that each key is the name of something CloudPowers can interact with Parameters hash Returns Boolean

Returns:

  • (Boolean)


259
260
261
262
# File 'lib/cloud_powers/context.rb', line 259

def valid_hash_format?(hash)
  keys_arr = hash.keys.map { |key| to_pascal(key).to_sym }
  (keys_arr - available_resources).empty?
end

#valid_json_format?(json_string) ⇒ Boolean

Parses the json_string which yields a Hash or an exception. From there, use the #valid_hash_format?() method

Returns:

  • (Boolean)


266
267
268
269
270
271
272
# File 'lib/cloud_powers/context.rb', line 266

def valid_json_format?(json_string)
  begin
    valid_hash_format?(JSON.parse(json_string))
  rescue JSON::ParserError
    false
  end
end