seapig-rails 0.0.6 → 0.0.7

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 534372c316056968d765bff6ef7f1d41f2e93734
4
- data.tar.gz: 15aa1b58cb7309ebc2e72df46b198e6783448328
3
+ metadata.gz: 42061dcf4ac1f6917849a446a9c7c172d32410ab
4
+ data.tar.gz: 9e4b9e713cfe8beb6c219b488bb561df4e8a0af2
5
5
  SHA512:
6
- metadata.gz: 2f04cb720f9e68a5581898f38add51bd6ac177bb4478c53b58175e488a0dc52a42102a704c917d32ecf94d755f0fd052cd712dd7184a7044ea3d9442da1d8e02
7
- data.tar.gz: eaee9f1518774181cfeb2ea8d139838729735d8fe6e918379c75f0627a075a63b71cabc4fd34d3464b2dfcbe6005714fe904c2a74dc4409d84ef3153a9fac24b
6
+ metadata.gz: 00424c408f4db3d6a4ff1b9e609b70bc44518578013ac1af18cb363439f1462621b67f7e6527536e7ded8314dd40ce6fc4b4bc6231fddf2910e6d5db6113a6b7
7
+ data.tar.gz: b905c978f13c69f34395b5b80dca458a59424140370f54c57866f911a9bc9f95518fa72a2427b23e5a10e14d6c217c7726ea71a6209eab563b8151f69223c591
@@ -0,0 +1,153 @@
1
+ @e = (content)->
2
+ content.__seapig_binding_element__ = {
3
+ }
4
+ content
5
+
6
+
7
+ class @SeapigBinding
8
+
9
+
10
+ constructor: (seapig_server, options = {})->
11
+ @seapig_server = seapig_server
12
+ @debug = options.debug
13
+ @view(options.view) if options.view
14
+ @onchange = options.onchange
15
+ @valid = false
16
+ @initialized = false
17
+ @object = false
18
+ @object_id = null
19
+ @elements = null
20
+ @shadow = { __seapig_binding_element__: {state: {},conflict: {},updated_at: {}}}
21
+ @selector = (data) -> data
22
+ @model(options.model) if options.model?
23
+
24
+ state: (element)->
25
+
26
+ view: (view)->
27
+ $(document).on('click',view+' .seapig-binding-element-delete', (event) =>
28
+ console.log('BINDING: A-element clicked.',event) if @debug
29
+ element = @element_find(event.target)
30
+ @element_remove(element[0],element[1],$(dom_element).hasClass('seapig-bindind-autosave'))
31
+ false
32
+ )
33
+
34
+
35
+ #FIXME: OOize all element_* methods
36
+
37
+ element_remove: (parent,id,save)->
38
+ console.log("removing", parent, id) if @debug
39
+
40
+ element_find: (dom_element)->
41
+ path = []
42
+ while dom_element
43
+ id = $(dom_element).attr('data-seapig-binding-element')
44
+ path.push(id) if id
45
+ dom_element = dom_element.parentElement
46
+ path = path.reverse()
47
+ id = path.pop()
48
+ parent = @elements
49
+ for step in path
50
+ parent = parent[step]
51
+ [parent, id]
52
+
53
+
54
+ update_element: (elements, key, shadows, shadow_key, element, remote) ->
55
+ if typeof(remote) == "object"
56
+ if typeof(remote) == "undefined" #delete
57
+ delete elements[key]
58
+ delete shadows[shadow_key]
59
+ else
60
+ if (element? != remote?) or (typeof(element) != typeof(remote)) or (Array.isArray(element) != Array.isArray(remote)) #(re-)create
61
+ element = if remote == null then null else if Array.isArray(remote) then [] else {}
62
+ shadows[shadow_key] = { __seapig_binding_element__: {state: {},conflict: {},updated_at: {}}}
63
+ elements[key] = element
64
+ @update(elements[key],shadows[shadow_key],remote) if element? #update
65
+ else
66
+ if typeof(remote) == "undefined" #delete
67
+ delete elements[key]
68
+ delete shadows[shadow_key]
69
+ else #update
70
+ elements[key] = remote
71
+ if element != remote
72
+ shadows[shadow_key] ||= { __seapig_binding_element__: {state: {},conflict: {},updated_at: {}}}
73
+ shadows[shadow_key].__seapig_binding_element__.updated_at[key] = new Date()
74
+
75
+
76
+ update: (elements, shadow, remotes)->
77
+ throw "wut? a vampaya?" if not shadow?
78
+ console.log("updating",elements,shadow,remotes) if @debug
79
+
80
+
81
+ if Array.isArray(elements)
82
+ console.log('array') if @debug
83
+ elements_by_id = _.object(([(e? and e.id or i), e] for e,i in elements))
84
+ remotes_by_id = _.object(([(e? and e.id or i), e] for e,i in remotes))
85
+ shadow_shadow = _.object([k,v] for k,v of shadow)
86
+ console.log("elements_by_id, remotes_by_id", elements_by_id, remotes_by_id ) if @debug
87
+
88
+ added_elements = _.difference(_.keys(remotes_by_id),_.keys(elements_by_id))
89
+ removed_elements = _.difference(_.keys(elements_by_id),_.keys(remotes_by_id))
90
+ console.log("added", added_elements) if @debug
91
+ console.log("removed", removed_elements) if @debug
92
+ elements.length = 0
93
+ shadow.length = 0
94
+ for remote_element,i in remotes
95
+ id = (remote_element? and remote_element.id or i)
96
+ element = elements_by_id[id]
97
+ console.log('adding',remote_element,id,element) if @debug
98
+ @update_element(elements,i,shadow,id,element,remote_element)
99
+ console.log(elements) if @debug
100
+
101
+ else
102
+ console.log('object') if @debug
103
+ added_elements = _.difference(_.keys(remotes),_.keys(elements))
104
+ common_elements = _.intersection(_.keys(remotes),_.keys(elements))
105
+ removed_elements = _.difference(_.keys(elements),_.keys(remotes))
106
+ console.log("added", added_elements) if @debug
107
+ console.log("common", common_elements) if @debug
108
+ console.log("removed", removed_elements) if @debug
109
+
110
+ for element in added_elements
111
+ @update_element(elements,element,shadow,element,elements[element],remotes[element])
112
+
113
+ for element in removed_elements
114
+ switch shadow.__seapig_binding_element__.state[element]
115
+ when 'clean', undefined
116
+ @update_element(elements,element,shadow,element,elements[element],remotes[element])
117
+ else
118
+ console.log('filth! 1')
119
+
120
+ for element in common_elements
121
+ switch shadow.__seapig_binding_element__.state[element]
122
+ when 'clean', undefined
123
+ @update_element(elements,element,shadow,element,elements[element],remotes[element])
124
+ else
125
+ console.log('filth! 2')
126
+
127
+
128
+
129
+ model: (object_id)->
130
+ return if object_id == @object_id
131
+ @object_id = object_id
132
+
133
+ if @object
134
+ @object.unlink()
135
+ @valid = false
136
+ @initialized = false
137
+
138
+ if @object_id
139
+ @object = @seapig_server.slave(@object_id)
140
+ @object.onchange = ()=>
141
+ if @object.valid
142
+ console.log('BINDING: Data update received.') if @debug
143
+ new_elements = @selector(JSON.parse(JSON.stringify(@object.object)))
144
+ @elements ||= (if Array.isArray(new_elements) then [] else {})
145
+ @shadow ||= (if Array.isArray(new_elements) then [] else {})
146
+ @update(@elements,@shadow,new_elements)
147
+ @initialized = true
148
+ console.log(@elements) if @debug
149
+ @valid = @object.valid
150
+ @onchange() if @onchange
151
+ @data = @object.object
152
+
153
+ @onchange() if @onchange
@@ -22,6 +22,7 @@ class @SeapigServer
22
22
  console.log('Seapig connection closed') if @options.debug
23
23
  for object_id, object of @slave_objects
24
24
  object.valid = false
25
+ object.onchange() if object.onchange?
25
26
  setTimeout((=>@connect()), 2000)
26
27
 
27
28
  @socket.onopen = () =>
@@ -1,22 +1,26 @@
1
1
  class @SeapigRouter
2
2
 
3
3
 
4
- constructor: (seapig_server, session_id, initial_search, debug = false)->
4
+ constructor: (seapig_server, session_id, mountpoint, initial_search, debug = false)->
5
5
  @seapig_server = seapig_server
6
6
  @session_id = session_id
7
+ @mountpoint = mountpoint
7
8
  @debug = debug
8
9
  @initial_search = initial_search
9
10
 
10
11
  @state = {session_id: @session_id, id: 0}
12
+ @volatile = {}
11
13
 
12
14
  @session_data = @seapig_server.master('web-session-data-'+@session_id)
13
15
  @session_data.object.states = [ @state ]
14
16
  @session_data.sequence = 1
15
17
  @session_data.bases = {}
18
+ @session_data.diffs = {}
16
19
  @session_data.changed()
17
20
 
18
21
  @session_data_saved = @seapig_server.slave('web-session-saved-'+@session_id)
19
22
  @session_data_saved.onchange = ()=>
23
+ return if not @session_data_saved.valid
20
24
  while @session_data.object.states[0]? and @session_data.object.states[0].id < @session_data_saved.object.max_state_id
21
25
  @session_data.object.states.shift()
22
26
  console.log('Session saved, updating url:',@current_url()) if @debug
@@ -24,7 +28,6 @@ class @SeapigRouter
24
28
  window.history.replaceState(@state,null,@current_url()) if @state_valid
25
29
  @replacing_state = false
26
30
 
27
-
28
31
  @replacing_state = false
29
32
  @state_valid = false
30
33
 
@@ -37,77 +40,111 @@ class @SeapigRouter
37
40
  )
38
41
 
39
42
  window.onpopstate = (data) =>
43
+ previous_state = JSON.parse(JSON.stringify(@state))
40
44
  @state = data.state
41
- @state_changed()
42
-
45
+ @update_location()
46
+ @onstatechange(@state,previous_state) if @onstatechange?
43
47
 
44
48
 
45
- location_changed: () ->
46
- return if @replacing_state
47
- console.log('ROUTER: Location changed to: pathname:', window.location.pathname, ' search:', window.location.search) if @debug
48
-
49
- spl = window.location.pathname.split('/')
49
+ url_to_diff: (pathname, search)->
50
+ spl = pathname.split(@mountpoint)
50
51
  spl.shift()
52
+ spl = spl.join(@mountpoint).split('/')
51
53
  if spl.shift() == 'a'
52
54
  path_session_id = spl.shift()
53
55
  path_state_id = spl.shift()
54
56
  if not path_state_id
55
- window.history.replaceState(@state,null,'/a/'+@session_id+'/0'+window.location.search)
56
- return @location_changed()
57
+ return { replace: @mountpoint+'a/'+@session_id+'/0'+window.location.search }
57
58
  else
58
- window.history.replaceState(@state,null,'/a/'+@session_id+'/0?'+(@initial_search.replace(/^\?/,'')+window.location.search.replace(/^\?/,'&')).replace(/^&/,''))
59
- return @location_changed()
59
+ return { replace: @mountpoint+'a/'+@session_id+'/0?'+(@initial_search.replace(/^\?/,'')+window.location.search.replace(/^\?/,'&')).replace(/^&/,'') }
60
60
 
61
61
  total_diff = []
62
62
  partial_diff = []
63
63
  while spl.length > 0
64
64
  total_diff.push([spl.shift(),spl.shift()])
65
- if window.location.search.length > 0
66
- for pair in window.location.search.split('?')[1].split('&')
65
+ if search.length > 1
66
+ for pair in search.split('?')[1].split('&')
67
67
  total_diff.push(pair.split('=',2))
68
68
  partial_diff.push(pair.split('=',2))
69
+
69
70
  console.log('Parsed location: session_id:',path_session_id,' partial_diff:', partial_diff) if @debug
70
71
 
71
- if path_session_id == @session_id
72
- @state_change(partial_diff)
72
+ { total: total_diff, partial: partial_diff, session_id: path_session_id, state_id: path_state_id }
73
+
74
+
75
+ location_changed: () ->
76
+ return if @replacing_state
77
+ console.log('ROUTER: Location changed to: pathname:', window.location.pathname, ' search:', window.location.search) if @debug
78
+
79
+ diff = @url_to_diff(window.location.pathname,window.location.search)
80
+ if diff.replace?
81
+ console.log('ROUTER: Invalid url, replacing with:', diff.replace) if @debug
82
+ window.history.replaceState(@state,null,diff.replace)
83
+ return @location_changed()
84
+
85
+ if diff.session_id == @session_id
86
+ @state_change(diff.partial)
73
87
  else
74
88
  if @remote_state?
75
- @state_change_to_remote(total_diff)
89
+ @state_change_to_remote(diff.total) #oaueia
76
90
  else
77
91
  @state_valid = false
78
- if path_state_id == '0'
79
- @remote_state = {object: {session_id: path_session_id, id: 0}}
80
- @state_change_to_remote(total_diff)
92
+ if diff.state_id == '0'
93
+ @state = {session_id: diff.session_id, id: 0}
94
+ @state_change(diff.total)
81
95
  else
82
- @remote_state = @seapig_server.slave('web-session-state-'+path_session_id+':'+path_state_id)
83
- @remote_state.onchange = ()=> @state_change_to_remote(total_diff)
96
+ @remote_state = @seapig_server.slave('web-session-state-'+diff.session_id+':'+diff.state_id)
97
+ @remote_state.onchange = ()=>
98
+ return if not @remote_state.valid
99
+ @state = _.clone(@remote_state.object)
100
+ @state_change(diff.total)
101
+ @remote_state.unlink()
102
+ @remote_state = null
103
+
104
+
105
+ state_commit: () ->
106
+ if @state.uncommitted
107
+ console.log("Deferred commit") if @debug
108
+ delete @state.uncommitted
109
+ @session_data.object.states.push(@state)
110
+ @session_data.changed()
111
+ clearTimeout(@commit_timer) if @commit_timer
112
+ @commit_at = null
113
+ @commit_timer = null
114
+ @update_location()
84
115
 
85
116
 
86
- state_change_to_remote: (diff) ->
87
- @state = _.clone(@remote_state.object)
117
+ state_change: (diff,defer = 0) ->
118
+ commit_at = Date.now() + defer
119
+ previous_state = JSON.parse(JSON.stringify(@state))
88
120
  if diff.length > 0
89
- @state_change(diff)
90
- else
91
- #@session_data.object.states.push(@state)
92
- @state_valid = true
93
- @state_changed()
94
-
121
+ console.log("Applying change at:", defer, commit_at,"to",@state) if @debug
122
+ next_state = @state
123
+ if not @state.uncommitted?
124
+ base_state = @state
125
+ next_state = _.clone(@state)
126
+ next_state.session_id = @session_id
127
+ next_state.id = @session_data.sequence++
128
+ @session_data.bases[next_state.id] = base_state
129
+ @session_data.diffs[next_state.id] = []
130
+ next_state = @state_diff_apply(next_state, diff)
131
+ console.log("Pre-filter next-state", next_state)
132
+ @statefilter(next_state,previous_state) if @statefilter?
133
+ console.log("Post-filter next-state", next_state)
134
+ @state = next_state
135
+ @session_data.diffs[@state.id] = @session_data.diffs[@state.id].concat(diff)
136
+ if commit_at <= Date.now()
137
+ @state_commit()
138
+ else
139
+ @state.uncommitted = true
140
+ if (not @commit_at) or (commit_at < @commit_at)
141
+ console.log("Deferring commit by,till:", commit_at - Date.now(), commit_at) if @debug
142
+ clearTimeout(@commit_timer) if @commit_timer
143
+ @commit_at = commit_at
144
+ @commit_timer = setTimeout((()=> @state_commit()), @commit_at - Date.now())
95
145
 
96
- state_change: (diff) ->
97
- base_state = @state
98
- @state = @state_diff_apply(_.clone(@state), diff)
99
- @state.diff = diff
100
- @statefilter(@state) if @statefilter?
101
- @state.session_id = @session_id
102
- @state.id = @session_data.sequence++
103
- @session_data.bases[@state.id] = base_state
104
- @session_data.object.states.push(@state)
105
- @session_data.changed()
106
- if @remote_state?
107
- @remote_state.unlink() if @remote_state.object.id > 0
108
- @remote_state = null
109
146
  @state_valid = true
110
- @state_changed()
147
+ @onstatechange(@state,previous_state) if @onstatechange?
111
148
 
112
149
 
113
150
  state_diff_apply: (state, diff)->
@@ -128,12 +165,12 @@ class @SeapigRouter
128
165
  if hash
129
166
  obj[spl[spl.length-1]] = value
130
167
  else
131
- obj[spl[spl.length-1]].push(value)
168
+ (obj[spl[spl.length-1]] ||= []).push(value)
132
169
  else
133
170
  if hash
134
171
  delete obj[spl[spl.length-1]]
135
172
  else
136
- state[entry[0]].splice(_.indexOf(state[entry[0]], value),1)
173
+ obj[spl[spl.length-1]].splice(_.indexOf(obj[spl[spl.length-1]], value),1)
137
174
  state
138
175
 
139
176
 
@@ -151,17 +188,21 @@ class @SeapigRouter
151
188
  path_overlay = ""
152
189
  for state in chain
153
190
  console.log('-',state) if @debug
154
- path_overlay += @state_diff_to_path(state.diff)
155
-
156
- console.log('Calculated url:','/a/'+base_state.session_id+'/'+base_state.id+path_overlay) if @debug
157
- '/a/'+base_state.session_id+'/'+base_state.id+path_overlay
191
+ path_overlay += @state_diff_to_path(@session_data.diffs[state.id])
158
192
 
193
+ console.log('Calculated url:',@mountpoint+'a/'+base_state.session_id+'/'+base_state.id+path_overlay) if @debug
194
+ @mountpoint+'a/'+base_state.session_id+'/'+base_state.id+path_overlay
159
195
 
160
- state_changed: () ->
161
196
 
197
+ update_location: () ->
162
198
  console.log("ROUTER: State changed to: state:", @state, ' url:', @current_url()) if @debug
163
199
  @replacing_state = true
164
200
  window.history.replaceState(@state,null,@current_url())
165
201
  @replacing_state = false
166
202
 
167
- @onstatechange(@state) if @onstatechange?
203
+
204
+ stealth_change: (query, defer = 1000) ->
205
+ [pathname, search] = query.split("?")
206
+ pathname = window.location.pathname if pathname.length == 0
207
+ diff = @url_to_diff(pathname,"?"+(search or ""))
208
+ @state_change(diff.partial,defer)
@@ -0,0 +1,25 @@
1
+ class SeapigDependency < ActiveRecord::Base
2
+
3
+ def self.bump(*names) #FIXME: mass upsert / PG 9.5
4
+ self.transaction {
5
+ ret = names.map { |name|
6
+ value = self.find_by_sql(["UPDATE seapig_dependencies SET current_version = nextval('seapig_dependency_version_seq'), updated_at = now() WHERE name = ? RETURNING current_version", name])
7
+ value = self.find_by_sql(["INSERT INTO seapig_dependencies(name, current_version, reported_version, created_at, updated_at) VALUES (?,nextval('seapig_dependency_version_seq'),0,now(),now()) RETURNING current_version",name]) if value.size == 0
8
+ value[0].current_version
9
+ }
10
+ connection.instance_variable_get(:@connection).exec("NOTIFY seapig_dependency_changed")
11
+ }
12
+ end
13
+
14
+
15
+ def self.version(name)
16
+ self.versions(name)[name]
17
+ end
18
+
19
+
20
+ def self.versions(*names)
21
+ Hash[*self.find_by_sql(["SELECT names.name, COALESCE(sd.current_version,0) AS current_version FROM (SELECT unnest(ARRAY[?]) AS name) AS names LEFT OUTER JOIN seapig_dependencies AS sd ON names.name = sd.name", names]).map { |name| [name.name,name.current_version] }.flatten]
22
+ end
23
+
24
+
25
+ end
@@ -2,9 +2,6 @@ class SeapigRouterSession < ActiveRecord::Base
2
2
 
3
3
  has_many :seapig_router_session_states
4
4
 
5
- acts_as_seapig_dependency
6
-
7
-
8
5
  def self.generate
9
6
  session = SeapigRouterSession.new
10
7
  begin
@@ -2,6 +2,4 @@ class SeapigRouterSessionState < ActiveRecord::Base
2
2
 
3
3
  belongs_to :seapig_router_session
4
4
 
5
- acts_as_seapig_dependency
6
-
7
5
  end
data/bin/seapig-notifier CHANGED
@@ -1,36 +1,25 @@
1
1
  #!/bin/env ruby
2
2
 
3
- ENV['RAILS_ENV'] = 'production'
4
3
  require './config/environment.rb'
5
4
 
6
5
  require 'websocket-eventmachine-client'
7
6
  require 'json'
8
7
 
9
- notifiers = Hash[*ActiveRecord::Base.descendants.select { |cls| cls.respond_to?('seapig_dependency_version') }.map { |notifier| [notifier.name,notifier] }.flatten ]
10
8
 
11
- puts "Known notifiers:"
12
- notifiers.keys.each { |notifier| puts " "+notifier }
13
- puts
14
-
15
- $last_versions = {}
16
- $payloads = Queue.new
9
+ #ActiveRecord::Base.logger = Logger.new(STDERR)
17
10
 
18
11
  EM.run {
19
12
 
20
13
  socket = WebSocket::EventMachine::Client.connect(uri: ARGV[0])
21
-
14
+ connected = false
22
15
 
23
16
  on_database_change = Proc.new {
24
- payloads = Set.new
25
- payloads << $payloads.pop while not $payloads.empty?
26
- payloads.each { |notifier_name|
27
- version = notifiers[notifier_name].seapig_dependency_version #F handle wrong names
28
- p version
29
- if $last_versions[notifier_name] != version
30
- #socket.send(JSON.dump(action: 'object-update', id: notifier_name, version: version))
31
- socket.send(JSON.dump(action: 'object-patch', id: notifier_name, new_version: version, old_version: 0))
32
- $last_versions[notifier_name] = version
33
- end
17
+ next if not connected
18
+ SeapigDependency.where("current_version != reported_version").each { |seapig_dependency|
19
+ puts "Dependency version changed: %30s:%-10s"%[seapig_dependency.name,seapig_dependency.current_version]
20
+ socket.send(JSON.dump(action: 'object-patch', id: seapig_dependency.name, new_version: seapig_dependency.current_version, old_version: 0))
21
+ seapig_dependency.reported_version = seapig_dependency.current_version
22
+ seapig_dependency.save!
34
23
  }
35
24
  }
36
25
 
@@ -43,29 +32,26 @@ EM.run {
43
32
  connection.exec("LISTEN seapig_dependency_changed")
44
33
  loop {
45
34
  connection.wait_for_notify { |channel, pid, payloads|
46
- puts "Got notification: channel="+channel+", pid="+pid.inspect+", payload="+payloads.inspect
47
- payloads.split(",").each { |payload| $payloads << payload }
35
+ #puts "Got notification: channel="+channel+", pid="+pid.inspect+", payload="+payloads.inspect
48
36
  EM.schedule(on_database_change)
49
37
  }
50
38
  }
51
39
  }
52
40
  }
41
+ connected = true
53
42
  EM.schedule on_database_change
54
43
  }
55
44
 
56
-
45
+
57
46
  socket.onclose { |code, reason|
58
47
  EM.stop
59
48
  }
60
49
 
61
50
 
62
- EM.add_periodic_timer(60) {
63
- # socket.send(JSON.dump(action: 'object-update', id: 'Minute', version: Time.new.to_i/60))
64
- socket.send(JSON.dump(action: 'object-patch', id: 'Minute', new_version: Time.new.to_i/60, old_version: 0))
65
- }
66
-
67
- EM.add_periodic_timer(1) {
68
- socket.send(JSON.dump(action: 'object-patch', id: 'Second', new_version: Time.new.to_i, old_version: 0))
51
+ (ARGV[1] or "").split(',').each { |interval|
52
+ EM.add_periodic_timer(interval.to_i) {
53
+ socket.send(JSON.dump(action: 'object-patch', id: 'Seconds#'+interval, new_version: Time.new.to_i/interval.to_i, old_version: 0))
54
+ }
69
55
  }
70
56
  }
71
57
 
@@ -11,19 +11,22 @@ EM.run {
11
11
  SeapigServer.new(ARGV[0],name: 'session-saver').slave('web-session-data-*').onchange { |session_data|
12
12
  next if session_data.destroyed
13
13
  session_key = session_data.object_id
14
- p session_key
15
14
  session = SeapigRouterSession.find_by(key: session_key.split('-',4)[3])
16
- p session
15
+ if not session
16
+ puts "Ignoring unknown session: "+session_key
17
+ next
18
+ end
19
+ print "Saving session: "+session_key+" states: "
17
20
  max_state = session.seapig_router_session_states.order("state_id DESC").first
18
21
  max_state_id = (max_state and max_state.state_id or -1)
19
- p max_state, session_data['states'].map { |s| s['id'] }
20
22
  session_data['states'].each { |state|
21
- if state['id'] > max_state_id
22
- puts Time.new.to_s + " " + state.inspect
23
+ if state['id'] > max_state_id
24
+ print ' '+state['id'].inspect
23
25
  SeapigRouterSessionState.create!(seapig_router_session_id: session.id, state_id: state['id'], state: state)
24
26
  end
25
27
  }
26
- SeapigRouterSession.seapig_dependency_changed("SeapigRouterSessionState")
28
+ puts
29
+ SeapigDependency.bump("SeapigRouterSessionState#"+session.key)
27
30
  }
28
31
 
29
32
  }
@@ -0,0 +1,18 @@
1
+ class CreateSeapigVersions < ActiveRecord::Migration
2
+ def change
3
+ create_table :seapig_dependencies do |t|
4
+ t.text :name
5
+ t.bigint :current_version
6
+ t.bigint :reported_version
7
+
8
+ t.timestamps null: false
9
+ end
10
+
11
+ execute 'CREATE INDEX ON seapig_dependencies(name,current_version)'
12
+ execute 'CREATE INDEX ON seapig_dependencies((current_version != reported_version)) WHERE current_version != reported_version'
13
+ execute 'CREATE SEQUENCE seapig_dependency_version_seq OWNED BY seapig_dependencies.current_version'
14
+ end
15
+ end
16
+
17
+ # insert into seapig_dependencies (name,current_version,reported_version,created_at,updated_at) select 'reported' || generate_series, generate_series, generate_series, now(), now() from generate_series(1,1000000);
18
+ # insert into seapig_dependencies (name,current_version,reported_version,created_at,updated_at) select 'not-reported' || generate_series, generate_series, generate_series - 1 , now(), now() from generate_series(1,1000);
@@ -1,3 +1,3 @@
1
1
  module Seapig
2
- VERSION = "0.0.6"
2
+ VERSION = "0.0.7"
3
3
  end
data/lib/seapig-rails.rb CHANGED
@@ -1,5 +1,4 @@
1
1
  require "seapig/engine"
2
- require "seapig/acts_as_seapig_dependency.rb"
3
2
 
4
3
  module Seapig
5
4
  end
@@ -8,10 +8,9 @@ class SeapigRouterSessionSaved < Producer
8
8
  def self.produce(object_id)
9
9
  object_id =~ /web-session-saved-([^-]+)/
10
10
  session_key = $1
11
- version = {
12
- SeapigRouterSessionState: SeapigRouterSessionState.seapig_dependency_version
13
- }
11
+ version = SeapigDependency.versions('SeapigRouterSessionState#'+session_key)
14
12
  session = SeapigRouterSession.find_by(key: session_key)
13
+ return [false, version] if not session
15
14
  max_state = session.seapig_router_session_states.order("state_id DESC").first
16
15
  data = {
17
16
  max_state_id: (max_state and max_state.state_id or -1)
@@ -10,10 +10,10 @@ class SeapigRouterSessionStateProducer < Producer
10
10
  session_key = $1
11
11
  state_id = $2.to_i
12
12
  version = Time.new.to_f
13
- p session_key, object_id
14
13
  session = SeapigRouterSession.find_by(key: session_key)
14
+ return [false, SeapigDependency.versions('SeapigRouterSessionState#'+session_key)] if not session
15
15
  state = SeapigRouterSessionState.find_by(seapig_router_session_id: session.id, state_id: state_id)
16
- return [false, {SeapigRouterSessionState: SeapigRouterSessionState.seapig_dependency_version}] if not state
16
+ return [false, SeapigDependency.versions('SeapigRouterSessionState#'+session_key)] if not state
17
17
  data = state.state
18
18
  [data, version]
19
19
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: seapig-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.6
4
+ version: 0.0.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - yunta
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-03-28 00:00:00.000000000 Z
11
+ date: 2016-06-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -78,8 +78,10 @@ files:
78
78
  - MIT-LICENSE
79
79
  - README.rdoc
80
80
  - Rakefile
81
+ - app/assets/javascripts/seapig/seapig-binding.js.coffee
81
82
  - app/assets/javascripts/seapig/seapig-client.js.coffee
82
83
  - app/assets/javascripts/seapig/seapig-router.js.coffee
84
+ - app/models/seapig_dependency.rb
83
85
  - app/models/seapig_router_session.rb
84
86
  - app/models/seapig_router_session_state.rb
85
87
  - bin/seapig-notifier
@@ -87,8 +89,8 @@ files:
87
89
  - config/routes.rb
88
90
  - db/migrate/20151221110834_create_seapig_router_sessions.rb
89
91
  - db/migrate/20151221111628_create_seapig_router_session_states.rb
92
+ - db/migrate/20151228202111_create_seapig_versions.rb
90
93
  - lib/seapig-rails.rb
91
- - lib/seapig/acts_as_seapig_dependency.rb
92
94
  - lib/seapig/engine.rb
93
95
  - lib/seapig/version.rb
94
96
  - lib/seapigs/seapig_router_saved_session.rb
@@ -1,34 +0,0 @@
1
- module SeapigDependency
2
-
3
- module ActsAsSeapigDependency
4
-
5
- extend ActiveSupport::Concern
6
-
7
-
8
- module ClassMethods
9
-
10
- def acts_as_seapig_dependency(options = {})
11
-
12
- self.instance_eval do
13
-
14
- def seapig_dependency_version
15
- self.find_by_sql('SELECT GREATEST(MAX(created_at), MAX(updated_at)) AS version FROM '+table_name).first.version.to_f
16
- end
17
-
18
- def seapig_dependency_changed(*tables)
19
- tables << self.name
20
- connection.instance_variable_get(:@connection).exec("NOTIFY seapig_dependency_changed,'"+tables.map { |table| table.kind_of?(Class) and table.name or table }.uniq.join(',')+"'")
21
- end
22
-
23
- end
24
-
25
- end
26
-
27
- end
28
-
29
- end
30
-
31
- end
32
-
33
-
34
- ActiveRecord::Base.send :include, SeapigDependency::ActsAsSeapigDependency