Skip to content

Case Study: exhibits.stanford.edu

Jack Reed edited this page Apr 17, 2018 · 4 revisions

In deciding how to deploy our Spotlight applications, we decided to deploy each exhibit instance as a separate application mounted as sub-URIs on our exhibit host. This provides us with the most flexibility to provide exhibit-specific functionality, rolling updates to those exhibits, and a strong degree of isolation between the exhibits. For the first round of exhibits, these features were especially valuable in allowing us to be responsive to the needs of our curators.

Alternative approaches (and what we may migrate to later, should strong common patterns emerge) include:

  • multi-tenant Spotlight applications; Spotlight has basic support for multiple exhibits within the same application, sharing the same index and database. Although this may be the ideal configuration, it also would requires us to have all curators use the same application with the same base configuration, and require all customizations to be exposed as in-application features. In the interest of rapid development and being flexible responding to curator needs, we decided not to pursue this approach at that time.

  • multi-tenant Solr indexes (so all our exhibits would use the same Solr collection, and differentiate themselves using Spotlight::Engine.config.solr_fields.prefix, Spotlight::Engine.config.filter_resources_by_exhibit), including shared records for common resources. Although support for this configuration exists in Spotlight, data isolation and being able to provide exhibit-specific schemas (as needed) were important.

  • multi-tenant databases; while there exist Rails plugins (e.g. apartment) for sharing a single database across multiple applications, it seemed unnecessary in our environment

Exhibit Requests app

Given the approach we chose, we needed an automated way to create and deploy new exhibit instances. We built a common template application with Stanford-specific customizations to Spotlight (see below). We also built a simple requests application for curators to request a new exhibit, and some workflow logic to automate processing the request in order to deploy an application for them.

screen shot 2015-03-17 at 7 53 18 am

After submitting the form, the request enters into an ActiveJob queue (backed by sidekiq in our deployment) where it is picked up by various workers that:

  • create a new Solr collection using a base solr configuration,
  • create a new MySQL database,
  • prepare a deploy directory for Capistrano to deploy the application into,
  • deploys the application using Capistrano,
  • symlinks the application into the web server's document root and configures the application (using a .htaccess file) for Sub-URI deployment,
  • performs initial seed indexing (if requested), and
  • sends a notice to the curator that the exhibit was successfully created.

The process is fully asynchronous, and ActiveJob will retry failed steps several times before reporting failures to the service team.

Exhibit application

All exhibits currently share a common template application that provides some Stanford-specific configuration and behaviors.

PURL indexing

We're implemented on-demand resource indexing for PURL resources. This indexing uses the same indexing logic that we use when indexing digital resources into SearchWorks.

The curator can provide a list of digital object (or collection) identifiers and the application will index the items.

Resources:

SUL Embed viewer

Instead of using the OpenSeaDragon viewer against our image content directly, we consume an oEmbed-based service that provides embed code for SUL resources. We use the Blacklight configuration in our CatalogController to add a show partial:

# https://github.com/sul-dlss/sul-exhibits-template/blob/master/app/controllers/catalog_controller.rb#L49
class CatalogController ...
  configure_blacklight do |config|
     ...
     config.show.oembed_field = :url_fulltext
     config.show.partials.insert(1, :osd_or_embed)
     ...
  end
end

The oembed partial is provided by blacklight-oembed, and it renders the embeddable representation of the URL in the url_fulltext field in Solr.