rdf4j icon indicating copy to clipboard operation
rdf4j copied to clipboard

Repository level control of read/write and read-only

Open expe-elenigen opened this issue 1 year ago • 3 comments

Current Behavior

Here it's more a design issue that I want to point out, unless I misunderstood something.

For example, if I want to share the same MemoryStore for two different repositories, where one is read-only and the other is read-write.

    private val memoryStore = MemoryStore()
    private val rdfReaderRepository: Repository = SailRepository(memoryStore)
    private val rdfWriterRepository: Repository = SailRepository(memoryStore)

In this case, we have the function:

	@Override
	public boolean isWritable() throws RepositoryException {
		try {
			if (!isInitialized()) {
				init();
			}
			return sail.isWritable();
		} catch (SailException e) {
			throw new RepositoryException("Unable to determine writable status of Sail", e);
		}
	}

It means the repository is relying on the sail to know if it's read or write, but in my opinion, it should be possible to define the repository to read only even though the MemoryStore allows read-write.

Expected Behavior

We should be able to do this:

    private val memoryStore = MemoryStore()
    private val rdfReaderRepository: Repository = SailRepository(memoryStore, false)
    private val rdfWriterRepository: Repository = SailRepository(memoryStore, true)

Where the additional parameter allows to define if it's writable or not, under the hood, if we pass true but the memory store itself is configured with false, we should throw an exception, but otherwise I don't see why we couldn't restrict the access to read only.

As a workaround, we could also use the SailWrapper to change the response from the MemoryStore implementation, but that would look more like a workaround.

Steps To Reproduce

    private val memoryStore = MemoryStore()
    private val rdfReaderRepository: Repository = SailRepository(memoryStore)
    private val rdfWriterRepository: Repository = SailRepository(memoryStore)

Version

4.2.4

Are you interested in contributing a solution yourself?

No

Anything else?

In my case, I simply try to simulate the AWS Neptune endpoints with read only access vs read-write, so to have more accurate tests, it's important to be able to limit the type of queries we are building with the Repository.

expe-elenigen avatar May 18 '23 17:05 expe-elenigen

It isn't intended to share a Sail between multiple SailRepositories. I know others have solved similar issues at the endpoint level, ex. ReadOnlySparqlApplication.java

hmottestad avatar May 18 '23 19:05 hmottestad

I feel the in-memory solution is very good and the design should be extended in that case, because if you want to simulate a DB, then it would make sense in my opinion have the option to define if the repository is read only or not and share the same DB with multiple repositories. Don't you agree the SailWrapper would still be a good candidate to handle defining two different writable options for two repository? (in that case, it would be more a feature request)

expe-elenigen avatar May 18 '23 20:05 expe-elenigen

It's definitely a use case that is worth investigating. I would lean towards an authentication/role-based solution instead since that would solve what you are trying to do while at the same time allowing for more flexibility.

@abrokenjester knows more about the intentions behind the architecture than I do. Maybe he can chime in on the idea of sharing a sail between multiple repositories, and if adding restrictions like read-only would work at the repository level.

hmottestad avatar May 19 '23 07:05 hmottestad