Potential Implementation Paths
Develop a “Hyrax” adapter which stores everything in Fedora/Solr the same way as AF does with Hyrax, then update Hyrax’s controllers to use Valkyrie’s API. (Swap out ActiveFedora - no data migration)
Keep data - write an adapter to talk to data that exists. Don’t use AF.
Code work only - no data migrations.
Don’t have to maintain AF - just Valkyrie.
Highest chance for performance increase while using Fedora.
Raw Fedora adapter has shown good performance so far.
Can do solr updates in bulk at the end of a set of inserts, speeding that up.
Might be hard.
Complex situations include indirect containers for membership, cleaning up relationships, direct containers for files, a sub-node for membership, etc.
May not be able to take into account hacks on top of AF some implementations have used for things like deeply nested data. These folks may have to write their own adapters.
Risk of adapter becoming bloated.
Change Hyrax controllers to use Valkyrie API, use the ActiveFedora adapter (and make it so the AF resource is configurable.)
Keep data - use AF adapter to talk to data that exists. Valkyrie in front of AF.
Might not be much work to implement.
Code work only - no data migrations.
Things will probably be slower. It’s another abstraction.
If something breaks, it’s likely to be hard to track down.
Now we have to maintain Valkyrie & ActiveFedora as a community.
Switch controllers in Hyrax to use Valkyrie, then choose an adapter to use. Write a migration script to go from old data model to what the current Fedora adapter does.
Don't have to maintain AF - just use Valkyrie
Good chance of performance increase - just choose a fast adapter to migrate to.
Simple. The adapter exists.
Requires data migration
Migration may be different for each institution depending on how/what kind of data they store.
Who writes the script?
Are we happy with what the data model that exists in Hyrax now?
Current Raw Fedora adapter doesn’t do things like (because they’re unnecessary for the application to work):
Write some sort of backwards compatible layer - models that respond to #save but call a persister, form objects which fall back to ChangeSets, etc.
No code OR data migration
You could still switch metadata adapters.
Deep magic. This is at least 2 more layers of abstraction.
How do you unwind this after you migrate?
What happens when things break?
All or nothing.
One of the goals of the data mapper group was to make the stack simpler - this is more complex.
Hyrax Features Which Might Be Changed
The Valkyrie MVP app used a “ChangeSetPersister” pattern rather than Actors to solve the problem of callbacks and things like separating out ingesting of files. We’ve been happy with this, but Hyrax currently uses a set of actors.
Jobs would likely have to change in order to accept a ChangeSetPersister or something in order to know where to store files/metadata.
Actors could take a ChangeSetPersister and use them.
Code migration probably relatively easy.
Actors could be used instead of ChangeSetPersisters.
Migration easiest (probably.) You’d have to register metadata adapters and storage adapters to use.
Actors could go away.
Likely a significant code migration.
(Figgy does this.)
The Valkyrie MVP app stores the File ID of the derivative in the resource, so it can be stored wherever you like and the logic doesn’t have to change.
Hyrax just has code to go from ID -> spot on disk where derivative should be, and it goes and fetches it.
The least amount of code change would be to stick with the Hyrax method.
Valkyrie provides a CharacterizationService for registering characterization methods. A FITS service will have to be written, or the CharacterizationService abstraction ignored.
LDP in PCDM
The Fedora adapter doesn’t do indirect containers for membership. If this is important, it will have to be implemented.
Valkyrie Resources have no concept of predicates or what their RDF serialization would be. They’re an abstract model. The RDF serialization logic in Hyrax will have to map a context on top of it, rather than just dumping the graph from Fedora.
Figgy implements this here: https://github.com/pulibrary/figgy/blob/master/app/models/concerns/linked_data.rb
Valkyrie uses Reform to power its ChangeSets, which get fed into things like simple_form. Hyrax will either have to migrate to that, or find some sort of intermediary adapter to use.
Hyrax Features Which May Be Tough
The Data Mapper Working Group didn’t attempt to implement Sipity. However, the code for Sipity only requires GlobalID to be implemented for models. This is reasonably possible, although you’d have to store which metadata adapter to pull the object from as part of the GlobalID.
The Data Mapper Working Group didn’t get this implemented during its sprints. However, we feel that a special “alternate_identifier” property could be added along with a query which would satisfy this use case.
The NOID implementation that currently exists in Hyrax assumes the application can control the ID which gets saved, but some backends prefer to generate their own ID (like Postgres.)
Each query that is added to Valkyrie requires reserving a special property on models for a certain use case. We don’t want to do this for every possible property, but there are times when an application will need a special query and will have to add one.
We provided a mechanism for doing this here: https://github.com/samvera-labs/valkyrie/pull/245
The mechanism hasn’t been extensively tested to see how it feels to use.
Hyrax uses Hydra::AccessControls to store WebACLs for permissions, which are persisted in Fedora. The Valkyrie Fedora adapter doesn’t do this, currently.
Bake it into the Fedora adapter. When it gets `read_groups`, `read_users`, `edit_users`, `edit_groups`, it persists them as WebACLs in Fedora. When someone asks for the resource, it performs all the queries to populate those fields on the model.
Treat permissions as special, and allow a way to provide a permissions strategy which decides how to serialize/unserialize the fields above for every persister. One would query, one would write to the object itself.
Treat ACLs & permissions as application logic. Just store the acl_id like other relationships, provide an indexer which can travel that relationship and index appropriately.
Option #3 would result in the least amount of code in Valkyrie, and we’d recommend trying it to see if it will work. If not, either of the other options will work.
Potential New Features
Persist to Fedora async
Since you’re able to define the persister to use, and all persisters use the same interface, one could persist to a faster backend first and then have a job persist that resource to Fedora in the background - if it makes sense to do so.
Run specs using an in-memory adapter