Versioned Objects

An object that has versioning capabilities in Skylark is called a “versioned object”. Like all Skylark objects, versioned objects have fields that contain values. But, compared to standard objects, versioning provides additional features:

They retain all the values that their fields took over time.

They can translations in multiple languages of the values of their fields.

When deleted, objects are made inaccessible from the API but are not removed from the database. The value of a deleted object can be retrieved by Ostmodern support.

They can be ingested en masse from an upstream data source (such as a media asset management, cataglogue, or scheduling tool). An object modified after being ingested can be reverted to its upstream version.

Use Cases

  • Versioned objects in Skylark help solve the following problems:
  • Serve content in several languages, with the ability to provide translation to any kind of data.
  • For instance, provide a different translation of a banner or a video depending on the language of the user.
  • Easily revert objects to their previous versions
  • Recover any kind of data, from deleted objects to older versions of objects
  • During a campaign, give the description of your content a more friendly tone on your Skylark instance, while keeping the more formal original description in your database. At the end of the campaign, simply revert the content’s original description.

Technical Description

When queried from the API, a versioned object is returned as a single flat object queried from the datastore. In reality to implement the features discussed above, versioned objects are stored in a slightly more complex way.

Stored as Multiple Objects

These are represented below.


The MetaFieldset contains information about the object itself. The RelationFieldset contains links from this object to others. The TranslatableFieldset and NonTranslatableFieldset contain all other information, depending on whether they are natural language fields requiring translation.

For instance, a Season object is described as such:

  • Linked to one Brand and several schedules in the RelationFieldset
  • Has an release date and a number of scenes (non-translatable) in the NonTranslatableFieldset
  • Also have a description and a title (translatable) TranslatableFieldset

The following classes would be created to implement Season


Creating a Versioned Object

When creating or updating an object, a JSON representation is passed to Skylark from which it creates an object. Four fieldsets will be created as part of the process, one for each of the objects defined above.

First, the MetadataFieldset. If the object does not yet exist, a MetadataFieldset is created. The object’s uid is generated if it was not provided, then set on the MetadataFieldset. Otherwise, if the object does exist, the MetadataFieldset for the existing object is retrieved from the datastore.

Next, the three other fieldsets are always created from the input JSON by distributing the values from the input appropriately. The language of the submitted details also stored in the TranslatableFieldset.

These fieldsets are not always saved to the datastore, as described in the next section.

Storing a Versioned Object

The way these fieldsets are stored in the datastore is represented by the diagram below.


There are three stores where the objects goes:

  • The Local store
  • The Upstream store
  • The Non-versioned store

Throughout the rest of this section, the most recent fieldset that has the same class and language than one that is about to be put in the datastore will be referred to as its predecessor. For instance, the latest MetaFieldset is the predecessor of the MetaFieldset that is about to be put in the datastore.

Deciding on the store for a Fieldset

When a versioned object is saved, both its RelationFieldset and its MetaFieldset are placed in the non-versioned store (this means that relationships to other objects are not versioned).

Its NonTranslatableFieldset and TranslatableFieldset are placed in the Local store if it was created using the regular create or update APIs. If they were created using the data-source APIs (generally during an ingest process), the copies are placed in the Upstream store. The Local store may also be updated, as explained later.

Deciding if predecessor versions are kept

When saving a fieldset to the Upstream store or the Non-versioned source, the predecessor version is replaced and no history is stored.

However, when saving a fieldset in the Local store, it is saved in addition to its predecessor, becoming the new current version if changes have been made. If no changes have been made, no new version is saved.

Versioning fields

The following fields are available on the TranslatableFieldset and NonTranslatableFieldset and will be returned to authorized users on Skylark environments configured for write access.

publish_on, modifiedthe date and time at which the fieldset was created in the datastore
ends_onthe date and time at which the fieldset ceased to be current. Effectively, its successor’s publish_on, or this version is the current version, null.
modified_bythe user that posted this version
version_numberthe version number as an integer. Effectively its predecessor’s version_number+1

Returning a Complete Versioned Object

The multiple fieldsets that make up a versioned object are flattened into a list of fields before returning it. This process is guided by two parameters: uid and language.

The first step is to retrieve the matching fieldsets. The correct MetaFieldset and RelationFieldset for the object are retrieved from the datastore. Additionally, the current NonTranslatableFieldset and the current TranslatableFieldset in the desired language are retrieved.

Their data is then merged into a single JSON object the complete flattened object is returned.

The data as ingested from upstream (stored in the upstream source) is used instead of the local version if the data-source APIs are used.

Deleting a Versioned Object

When an object is deleted using the API, its MetaFieldset’s deleted attribute is changed to true. It is then no longer available through the API, and requests for it by UID will return a 410 Gone status.

As well as common the common API endpoints, all versioned objects support the following endpoints: