Class: Cosmos::NarrativeModel
- Defined in:
- lib/cosmos/models/narrative_model.rb
Constant Summary collapse
- CHRONICLE_TYPE =
'narrative'.freeze
- PRIMARY_KEY =
'__NARRATIVE'.freeze
Instance Attribute Summary collapse
-
#color ⇒ Object
readonly
Returns the value of attribute color.
-
#description ⇒ Object
readonly
Returns the value of attribute description.
-
#duration ⇒ Object
readonly
Returns the value of attribute duration.
-
#start ⇒ Object
readonly
Returns the value of attribute start.
-
#stop ⇒ Object
readonly
Returns the value of attribute stop.
-
#type ⇒ Object
readonly
Returns the value of attribute type.
Attributes inherited from Model
#name, #plugin, #scope, #updated_at
Class Method Summary collapse
-
.all(scope:, limit: 100) ⇒ Array<Hash>
Array up to the limit of the models (as Hash objects) stored under the primary key.
-
.count(scope:) ⇒ Integer
Count of the members stored under the primary key.
-
.destroy(scope:, score:) ⇒ Integer
Remove member from a sorted set based on the score.
-
.from_json(json, scope:) ⇒ NarrativeModel
Model generated from the passed JSON.
-
.get(start:, stop:, scope:, limit: 100) ⇒ Array|nil
Array up to 100 of this model or empty array.
- .pk(scope) ⇒ Object
-
.range_destroy(scope:, min:, max:) ⇒ Integer
Remove members from min to max of the sorted set.
-
.score(score:, scope:) ⇒ String|nil
String of the saved json or nil if score not found under primary_key.
Instance Method Summary collapse
-
#as_json ⇒ Hash
Generated from the NarrativeModel.
-
#create ⇒ Object
Update the Redis hash at primary_key and set the score equal to the start Epoch time the member is set to the JSON generated via calling as_json.
-
#destroy ⇒ Object
destroy the activity from the redis database.
-
#initialize(scope:, start:, stop:, color:, description:, type: CHRONICLE_TYPE, updated_at: 0, duration: 0) ⇒ NarrativeModel
constructor
A new instance of NarrativeModel.
-
#notify(kind:, extra: nil) ⇒ Object
-
update the redis stream / timeline topic that something has changed.
-
-
#set_input(start:, stop:, color:, description:) ⇒ Object
Set the values of the instance, @start, @stop, @description…
-
#to_s ⇒ String
String view of NarrativeModel.
-
#update(start:, stop:, color:, description:) ⇒ Object
Update the Redis hash at primary_key and remove the current activity at the current score and update the score to the new score equal to the start Epoch time this uses a multi to execute both the remove and create.
-
#validate_color(color) ⇒ Object
validate color.
-
#validate_input(start:, stop:, color:, description:) ⇒ Object
validate the input to the rules we have created for timelines.
-
#validate_time(ignore_score: nil) ⇒ Object
validate_time will be called on create and update this will validate that no other chronicle event or metadata had been saved for that time.
Methods inherited from Model
#as_config, #deploy, filter, find_all_by_plugin, get_all_models, get_model, handle_config, names, set, #undeploy
Constructor Details
#initialize(scope:, start:, stop:, color:, description:, type: CHRONICLE_TYPE, updated_at: 0, duration: 0) ⇒ NarrativeModel
Returns a new instance of NarrativeModel.
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
# File 'lib/cosmos/models/narrative_model.rb', line 111 def initialize( scope:, start:, stop:, color:, description:, type: CHRONICLE_TYPE, updated_at: 0, duration: 0 ) super(NarrativeModel.pk(scope), name: start.to_s, scope: scope) set_input( start: start, stop: stop, color: color, description: description, ) @type = type @updated_at = updated_at end |
Instance Attribute Details
#color ⇒ Object (readonly)
Returns the value of attribute color.
104 105 106 |
# File 'lib/cosmos/models/narrative_model.rb', line 104 def color @color end |
#description ⇒ Object (readonly)
Returns the value of attribute description.
104 105 106 |
# File 'lib/cosmos/models/narrative_model.rb', line 104 def description @description end |
#duration ⇒ Object (readonly)
Returns the value of attribute duration.
104 105 106 |
# File 'lib/cosmos/models/narrative_model.rb', line 104 def duration @duration end |
#start ⇒ Object (readonly)
Returns the value of attribute start.
104 105 106 |
# File 'lib/cosmos/models/narrative_model.rb', line 104 def start @start end |
#stop ⇒ Object (readonly)
Returns the value of attribute stop.
104 105 106 |
# File 'lib/cosmos/models/narrative_model.rb', line 104 def stop @stop end |
#type ⇒ Object (readonly)
Returns the value of attribute type.
104 105 106 |
# File 'lib/cosmos/models/narrative_model.rb', line 104 def type @type end |
Class Method Details
.all(scope:, limit: 100) ⇒ Array<Hash>
Returns Array up to the limit of the models (as Hash objects) stored under the primary key.
56 57 58 59 60 61 62 63 64 |
# File 'lib/cosmos/models/narrative_model.rb', line 56 def self.all(scope:, limit: 100) pk = self.pk(scope) array = Store.zrange(pk, 0, -1, :limit => [0, limit]) ret_array = Array.new array.each do |value| ret_array << JSON.parse(value) end return ret_array end |
.count(scope:) ⇒ Integer
Returns count of the members stored under the primary key.
67 68 69 |
# File 'lib/cosmos/models/narrative_model.rb', line 67 def self.count(scope:) return Store.zcard(self.pk(scope)) end |
.destroy(scope:, score:) ⇒ Integer
Remove member from a sorted set based on the score.
83 84 85 86 |
# File 'lib/cosmos/models/narrative_model.rb', line 83 def self.destroy(scope:, score:) pk = self.pk(scope) Store.zremrangebyscore(pk, score, score) end |
.from_json(json, scope:) ⇒ NarrativeModel
Returns Model generated from the passed JSON.
96 97 98 99 100 101 102 |
# File 'lib/cosmos/models/narrative_model.rb', line 96 def self.from_json(json, scope:) json = JSON.parse(json) if String === json raise "json data is nil" if json.nil? json.transform_keys!(&:to_sym) self.new(**json, scope: scope) end |
.get(start:, stop:, scope:, limit: 100) ⇒ Array|nil
Returns Array up to 100 of this model or empty array.
42 43 44 45 46 47 48 49 50 51 52 53 |
# File 'lib/cosmos/models/narrative_model.rb', line 42 def self.get(start:, stop:, scope:, limit: 100) if start > stop raise MetadataInputError.new "start: #{start} must be before stop: #{stop}" end pk = self.pk(scope) array = Store.zrangebyscore(pk, start, stop, :limit => [0, limit]) ret_array = Array.new array.each do |value| ret_array << JSON.parse(value) end return ret_array end |
.pk(scope) ⇒ Object
37 38 39 |
# File 'lib/cosmos/models/narrative_model.rb', line 37 def self.pk(scope) return "#{scope}#{PRIMARY_KEY}" end |
.range_destroy(scope:, min:, max:) ⇒ Integer
Remove members from min to max of the sorted set.
90 91 92 93 |
# File 'lib/cosmos/models/narrative_model.rb', line 90 def self.range_destroy(scope:, min:, max:) pk = self.pk(scope) Store.zremrangebyscore(pk, min, max) end |
.score(score:, scope:) ⇒ String|nil
Returns String of the saved json or nil if score not found under primary_key.
72 73 74 75 76 77 78 79 |
# File 'lib/cosmos/models/narrative_model.rb', line 72 def self.score(score:, scope:) pk = self.pk(scope) array = Store.zrangebyscore(pk, score, score, :limit => [0, 1]) array.each do |value| return JSON.parse(value) end return nil end |
Instance Method Details
#as_json ⇒ Hash
Returns generated from the NarrativeModel.
263 264 265 266 267 268 269 270 271 272 273 |
# File 'lib/cosmos/models/narrative_model.rb', line 263 def as_json return { 'color' => @color, 'start' => @start, 'stop' => @stop, 'description' => @description, 'type' => CHRONICLE_TYPE, 'scope' => @scope, 'updated_at' => @updated_at, } end |
#create ⇒ Object
Update the Redis hash at primary_key and set the score equal to the start Epoch time the member is set to the JSON generated via calling as_json
201 202 203 204 205 206 207 208 209 210 211 |
# File 'lib/cosmos/models/narrative_model.rb', line 201 def create validate_input(start: @start, stop: @stop, color: @color, description: @description) collision = validate_time() unless collision.nil? raise NarrativeOverlapError.new "no chronicles can overlap, collision: #{collision}" end @updated_at = Time.now.to_nsec_from_epoch Store.zadd(@primary_key, @start, JSON.generate(as_json())) notify(kind: 'created') end |
#destroy ⇒ Object
destroy the activity from the redis database
242 243 244 245 |
# File 'lib/cosmos/models/narrative_model.rb', line 242 def destroy Store.zremrangebyscore(@primary_key, @start, @start) notify(kind: 'deleted') end |
#notify(kind:, extra: nil) ⇒ Object
Returns [] update the redis stream / timeline topic that something has changed.
248 249 250 251 252 253 254 255 256 257 258 259 260 |
# File 'lib/cosmos/models/narrative_model.rb', line 248 def notify(kind:, extra: nil) notification = { 'data' => JSON.generate(as_json()), 'kind' => kind, 'type' => 'calendar', } notification['extra'] = extra unless extra.nil? begin CalendarTopic.write_entry(notification, scope: @scope) rescue StandardError => e raise NarrativeError.new "Failed to write to stream: #{notification}, #{e}" end end |
#set_input(start:, stop:, color:, description:) ⇒ Object
Set the values of the instance, @start, @stop, @description…
166 167 168 169 170 171 172 173 174 175 176 177 178 |
# File 'lib/cosmos/models/narrative_model.rb', line 166 def set_input(start:, stop:, color:, description:) begin DateTime.strptime(start.to_s, '%s') DateTime.strptime(stop.to_s, '%s') rescue ArgumentError raise NarrativeInputError.new "invalid input must be seconds: #{start}, #{stop}" end @start = start @stop = stop @duration = @stop - @start @color = color @description = description end |
#to_s ⇒ String
Returns string view of NarrativeModel.
276 277 278 |
# File 'lib/cosmos/models/narrative_model.rb', line 276 def to_s return "<NarrativeModel ->: #{@start}, x: #{@stop}, c: #{@color}, d: #{@description}>" end |
#update(start:, stop:, color:, description:) ⇒ Object
Update the Redis hash at primary_key and remove the current activity at the current score and update the score to the new score equal to the start Epoch time this uses a multi to execute both the remove and create. The member via the JSON generated via calling as_json
216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 |
# File 'lib/cosmos/models/narrative_model.rb', line 216 def update(start:, stop:, color:, description:) validate_input(start: start, stop: stop, color: color, description: description) old_start = @start set_input( start: start, stop: stop, color: color, description: description, ) @updated_at = Time.now.to_nsec_from_epoch collision = validate_time(ignore_score: old_start) unless collision.nil? raise NarrativeOverlapError.new "failed to update #{old_start}, no chronicles can overlap, collision: #{collision}" end Store.multi do |multi| multi.zremrangebyscore(@primary_key, old_start, old_start) multi.zadd(@primary_key, @start, JSON.generate(as_json())) end notify(kind: 'updated', extra: old_start) return @start end |
#validate_color(color) ⇒ Object
validate color
133 134 135 136 137 138 139 140 141 142 143 144 |
# File 'lib/cosmos/models/narrative_model.rb', line 133 def validate_color(color) if color.nil? color = '#%06x' % (rand * 0xffffff) end valid_color = color =~ /(#*)([0-9,a-f,A-f]{6})/ if valid_color.nil? raise MetadataInputError.new "invalid color but in hex format. #FF0000" end color = "##{color}" unless color.start_with?('#') return color end |
#validate_input(start:, stop:, color:, description:) ⇒ Object
validate the input to the rules we have created for timelines.
-
An entry’s start MUST be before the stop.
-
An entry’s description MUST a String.
149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 |
# File 'lib/cosmos/models/narrative_model.rb', line 149 def validate_input(start:, stop:, color:, description:) begin DateTime.strptime(start.to_s, '%s') DateTime.strptime(stop.to_s, '%s') rescue Date::Error raise NarrativeInputError.new "failed validation input must be seconds: #{start}, #{stop}" end validate_color(color) duration = stop - start if duration <= 0 raise NarrativeInputError.new "start: #{start} must be before stop: #{stop}" elsif description.is_a?(String) == false raise NarrativeInputError.new "description must be a String: #{description}" end end |
#validate_time(ignore_score: nil) ⇒ Object
validate_time will be called on create and update this will validate that no other chronicle event or metadata had been saved for that time. One event or metadata per second to ensure data can be updated.
186 187 188 189 190 191 192 193 194 195 196 197 |
# File 'lib/cosmos/models/narrative_model.rb', line 186 def validate_time(ignore_score: nil) array = Store.zrangebyscore(@primary_key, @start, @start, :limit => [0, 1]) array.each do |value| entry = JSON.parse(value) if ignore_score == entry['start'] next else return entry end end return nil end |