Class: ResolveController

Inherits:
ApplicationController show all
Defined in:
app/controllers/resolve_controller.rb

Overview

Requests to the Resolve controller are OpenURLs. There is one exception: Instead of an OpenURL, you can include the parameter umlaut.request_id=[some id] to hook up to a pre-existing umlaut request (that presumably was an OpenURL).

Constant Summary

@@no_create_request_actions =

Init processing will look at this list, and for actions mentioned, will not create a @user_request if an existing one can't be found. Used for actions meant only to deal with existing requests.

['background_update']

Class Attribute Summary (collapse)

Instance Method Summary (collapse)

Methods inherited from ApplicationController

#app_before_filter, #calculate_url_for_response, #error_404, #escape_xml, #frameset_action_url, #log_error, #log_processing, #params_preserve_xhr, #url_for_with_co

Class Attribute Details

+ (Object) background_service_timeout

Returns the value of attribute background_service_timeout



23
24
25
# File 'app/controllers/resolve_controller.rb', line 23

def background_service_timeout
  @background_service_timeout
end

+ (Object) requeue_failedtemporary_services

Returns the value of attribute requeue_failedtemporary_services



33
34
35
# File 'app/controllers/resolve_controller.rb', line 33

def requeue_failedtemporary_services
  @requeue_failedtemporary_services
end

Instance Method Details

- (Object) api



293
294
295
296
297
298
299
300
301
# File 'app/controllers/resolve_controller.rb', line 293

def api

  # Run the request if neccesary. 
  self.service_dispatch()
  @user_request.save!

  api_render()
  
end

- (Object) background_status

Display a non-javascript background service status page--or redirect back to index if we're done.



238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
# File 'app/controllers/resolve_controller.rb', line 238

def background_status

  unless ( @user_request.any_services_in_progress? )
    
    # Just redirect to ordinary index, no need to show progress status.
    # Include request.id, but also context object kev. 
    
    params_hash = 
       {:controller=>"resolve",
        :action=>'index', 
        'umlaut.skip_resolve_menu'.to_sym => params['umlaut.skip_resolve_menu'],
        'umlaut.request_id'.to_sym => @user_request.id }
    
    url = url_for_with_co( params_hash, @user_request.to_context_object )
    
    redirect_to( url )
  else
    # If we fall through, we'll show the background_status view, a non-js
    # meta-refresh update on progress of background services.
    # Your layout should respect this instance var--it will if it uses
    # the resolve_head_content partial, which it should.
    @meta_refresh_self = 5  
  end
end

- (Object) background_update

Action called by AJAXy thing to update resolve menu with new stuff that got done in the background.



229
230
231
232
233
234
# File 'app/controllers/resolve_controller.rb', line 229

def background_update
  unless (@user_request)
    # Couldn't find an existing request? We can do nothing.
    raise Exception.new("background_update could not find an existing request to pull updates from, umlaut.request_id #{params["umlaut.request_id"]}")
  end
end

The mini-menu itself.



221
222
223
# File 'app/controllers/resolve_controller.rb', line 221

def banner_menu
   self.setup_banner_link()
end

Show a link to something in a frameset with a mini menu in a banner.



200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
# File 'app/controllers/resolve_controller.rb', line 200

def bannered_link_frameset

    # Normally we should already have loaded the request in the index method,
    # and our before filter should have found the already loaded request
    # for us. But just in case, we can load it here too if there was a
    # real open url. This might happen on re-loads (after a long time or
    # cookie expire!) or in other weird cases.
    # If it's not neccesary, no services will be dispatched,
    # service_dispatch catches that. 
    self.service_dispatch()
    @user_request.save!
    
    self.setup_banner_link()

    # Use our new view with iframe instead of frameset.
    # Comment this out to go back to bannered_link_frameset
    # view with actual frameset. 
    render(:template => "resolve/bannered_link_iframe")
end

- (Object) display_coins

Useful for developers, generate a coins. Start from search/journals?umlaut.display_coins=true or search/books?umlaut.display_coins=true



195
196
197
# File 'app/controllers/resolve_controller.rb', line 195

def display_coins

end

- (Object) expire_old_responses

Expire expired service_responses if neccesary. See app config params 'response_expire_interval' and 'response_expire_crontab_format'.



74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'app/controllers/resolve_controller.rb', line 74

def expire_old_responses
  require 'CronTab'
  
  expire_interval = AppConfig.param('response_expire_interval')
  crontab_format = AppConfig.param('response_expire_crontab_format')

  unless (expire_interval || crontab_format)      
    # Not needed, nothing to expire
    return nil
  end
  
  responses_expired = 0
  @user_request.dispatched_services.each do |ds|

    now = Time.now
    
    expired_interval = expire_interval && 
      (now - ds.created_at > expire_interval)
    expired_crontab = crontab_format && 
      (now > CronTab.new(crontab_format).nexttime(ds.created_at))
    
    # Only expire completed ones, don't expire in-progress ones! 
    if (ds.completed && ( expired_interval || expired_crontab ))
        
        # Need to expire. Delete all the service responses, and
        # the DispatchedService record, and service will be automatically
        # run again. 
        
        serv_id = ds.service.service_id
        expired_responses = @user_request.service_types.each do |st|
          
          if st.service_response.service.service_id == serv_id
            @user_request.service_types.delete(st)
            responses_expired += 1
            st.service_response.destroy
            st.destroy
          end
        end
        @user_request.dispatched_services.delete(ds)
        ds.destroy
    end
  end
end

- (Object) index



146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
# File 'app/controllers/resolve_controller.rb', line 146

def index
  self.service_dispatch()

  # link is a ServiceType object
  link = should_skip_menu
  if ( ! link.nil? )
    if (params["umlaut.link_with_frameset"] !=  "false")
      url = frameset_action_url( link, {'umlaut.skipped_menu' => 'true'})
    else        
      new_params = { :controller => "link_router",
                 :action => "index",
                 :id => link.id }
    
      url = url_for(new_params)
    end
    redirect_to url
  else
    # Render configed view, if configed, or "index" view if not. 
    view = AppConfig.param("resolve_view", "resolve/index")
    render :template => view
  end

end

- (Object) init_processing

Retrives or sets up the relevant Umlaut Request, and returns it.



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'app/controllers/resolve_controller.rb', line 39

def init_processing
  options = {}
  if (  @@no_create_request_actions.include?(params[:action])  )
    options[:allow_create] = false
  end
  @user_request ||= Request.new_request(params, session, request, options )

  # If we chose not to create a request and still don't have one, bale out.
  return unless @user_request
  
  # Ip may be simulated with req.ip in context object, or may be
  # actual, request figured it out for us. 
  @collection = Collection.new(@user_request, session, params["umlaut.institution"])      
  @user_request.save!
  # Set 'timed out' background services to dead if neccesary. 
  @user_request.dispatched_services.each do | ds |
      if ( (ds.status == DispatchedService::InProgress ||
            ds.status == DispatchedService::Queued ) &&
            (Time.now - ds.updated_at) > self.class.background_service_timeout)

            ds.store_exception( Exception.new("background service timed out (took longer than #{self.class.background_service_timeout} to run); thread assumed dead.")) unless ds.exception_info
            # Fail it temporary, it'll be run again. 
            ds.status = DispatchedService::FailedTemporary
            ds.save!
            logger.warn("Background service timed out, thread assumed dead. #{@user_request.id} / #{ds.service.service_id}")
      end
  end
  
  return @user_request
end

- (Object) partial_html_sections

This action is for external callers. An external caller could get data as xml or json or whatever. But Umlaut already knows how to render it. What if the external caller wants the rendered content, but in discrete letter packets, a packet of HTML for each ServiceTypeValue? This does that, and also let's the caller know if background services are still running and should be refreshed, and gives the caller a URL to refresh from if neccesary.



271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
# File 'app/controllers/resolve_controller.rb', line 271

def partial_html_sections
  # Tell our application_helper#url_for to generate urls with hostname
  @generate_urls_with_host = true

  # Force background status to be the spinner--default js way of putting
  # spinner in does not generally work through ajax techniques.
  @force_bg_progress_spinner = true

  # Mark that we're doing a partial generation, because it might
  # matter later. 
  @generating_embed_partials = true
  
  @partial_html_sections = SectionRenderer.partial_html_sections.clone    
  
  # Run the request if neccesary. 
  self.service_dispatch()
  @user_request.save!

  self.api_render()
  
end

- (Object) register_request

inputs an OpenURL request into the system and stores it, but does NOT actually dispatch services to provide a response. Will usually be called by software, not a human browser. Sometimes it's useful to do this as a first step before redirecting the user to the actual resolve action for the supplied request--for instance, when the OpenURL metadata comes in a POST and can't be redirected.



176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
# File 'app/controllers/resolve_controller.rb', line 176

def register_request
  # init before filter already took care of setting up the request.
  @user_request.save!

  # Return data in headers allowing client to redirect user
  # to view actual response. 
  headers["x-umlaut-request_id"] = @user_request.id
  headers["x-umlaut-resolve_url"] = url_for( :controller => 'resolve', 'umlaut.request_id'.to_sym => @user_request.id )
  headers["x-umlaut-permalink_url"] = permalink_url( request, @user_request )

  # Return empty body. Once we have the xml response done,
  # this really ought to return an xml response, but with
  # no service responses yet available.
  render(:nothing => true)
end

- (Object) rescue_action_in_public(exception)



305
306
307
# File 'app/controllers/resolve_controller.rb', line 305

def rescue_action_in_public(exception)  
  render(:template => "error/resolve_error", :status => 500, :layout => AppConfig.param("resolve_layout", "resolve_basic")) 
end

- (Object) save_request



142
143
144
# File 'app/controllers/resolve_controller.rb', line 142

def save_request
  @user_request.save!
end


118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
# File 'app/controllers/resolve_controller.rb', line 118

def setup_banner_link
  # We keep the id of the ServiceType join object in param 'umlaut.id' for
  # banner frameset link type actions. Take it out and stick the object
  # in a var if available.    
  joinID = params['umlaut.id'.to_sym]
  
  @service_type_join = @user_request.service_types.find_all_by_id(joinID).first if joinID
  
  # default?    
  unless ( @service_type_join )
     
    @service_type_join = 
      @user_request.service_types.find_by_service_type_value_id(
    ServiceTypeValue[:fulltext].id )
  end

  

  unless @service_type_join 
     raise "No service_type_join found!. params[umlaut.id] == #{params['umlaut.id'.to_sym]}"
  end
  
end