Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JSON configuration persistence #17

Merged
merged 11 commits into from
Aug 10, 2020
Merged

JSON configuration persistence #17

merged 11 commits into from
Aug 10, 2020

Conversation

cgardens
Copy link
Contributor

@cgardens cgardens commented Aug 8, 2020

This PR creates an interface and implementation for how to persist configuration objects. Start with conduit-config-persistence/src/main/java/io/dataline/conduit/persistence/ConfigPersistence.java and conduit-config-persistence/src/main/java/io/dataline/conduit/persistence/ConfigPersistenceImpl.java.

The other changes in this PR are mostly just tweaks to the json schema.

@cgardens cgardens changed the title rw for json JSON configuration persistence Aug 10, 2020
@cgardens cgardens marked this pull request as ready for review August 10, 2020 20:09
import java.util.Set;

public interface ConfigPersistence {
<T> T getStandardConfig(
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lmk if there's a better way to do the generics here. ultimately the jackson library needs to interact with a Class object and i didn't want to do any reflection.

Copy link
Contributor

@sherifnada sherifnada left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So far so good!


public interface ConfigPersistence {
<T> T getConfig(
PersistenceConfigType persistenceConfigType, String configId, Class<T> clazz);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the purpose of PersistenceConfigType if we already provide clazz?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good question. clazz was a compromise implementation detail to get stuff to work. wish i could just get rid of that. if i drop the enum then the internals are going to have to do clazz.toString() and then run it through some switch statement. i think retaining the enum still makes what's going on clearer.


import java.util.Set;

public interface ConfigPersistence {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should all these methods throw so we can provide appropriate messages on the UI if needed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what do you want them to throw? right now i am catching all I/O exceptions internally and trying to put reasonable error messages.

Copy link
Contributor

@sherifnada sherifnada Aug 10, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if we have a throw in the signature of the methods, then the server has to handle exceptions well. Unless the impl you're going for is that these methods would throw reasonable messages and the server autowraps any failures nicely in a 500/400 in the UI? (and therefore doesn't need to wrap each individual failure)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

server autowraps any failures nicely in a 500/400

was not planning to do this.

can you give an example of what behavior you want? specifically what error you expect to have thrown and how the ui would interact with it?

Copy link
Contributor

@sherifnada sherifnada Aug 10, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if a config file is formatted incorrectly (fails validation), the UI should display a message saying for example: file is corrupt. Or if it is not found, should say file not found, please make sure your mount point is setup correctly. I'm imagining that since the server would be calling this persistence class, if the persistence class fails, we want to respond to the UI with a 400/500 with a human-readable message. I see two ways of doing this:

  1. every method throws, and the server wraps that and throws based on position of the failure in control flow. This is higher friction since the UI server must try-catch persistence operations.
  2. throw all un-fixable exceptions at the lowest level, and in the server whenever an exception is thrown, respond with a 500 whose message is exactly the failure message of the thrown exception

It seems like this impl is leaning towards no.2 above? this seems like a good choice since it's lowest friction.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can i punt on this until write some API endpoints and have a better feel for what will be ergonomic?

try {
objectMapper.writeValue(new File(getConfigPath(persistenceConfigType, configId)), config);
} catch (IOException e) {
throw new RuntimeException(e);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't these methods throw an IOException instead of rethrowing as a runtime exception?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can i punt on this until write some API endpoints and have a better feel for what will be ergonomic?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good.

return String.format("%s.json", id);
}

private ConfigSchema standardConfigTypeToConfigSchema(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the purpose of having two enums that are identical instead of just one?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ConfigSchema is mapping for name to file path. PersistenceConfigType is mean to be used as part of the interface but not tied to a file path.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any expectation for these to diverge in the future? This sort of switch/mapping feels like a bit of an antipattern.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure yet. i'm already regretting custom json disk persistence due to lack of ability to query by anything other than id.

@cgardens cgardens merged commit 4319ba4 into master Aug 10, 2020
@cgardens cgardens deleted the charles/rw_json branch August 10, 2020 22:32
@@ -31,4 +31,5 @@ dependencies {
}

jsonSchema2Pojo {
targetPackage = 'io.dataline.conduit.conduit_config'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Late to the party but it is weird to have conduit repeated twice. why not io.dataline.conduit.config

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

was just pattern matching other module names. the extra namespace can be dropped.

@@ -4,4 +4,4 @@ include 'conduit-api'
include 'conduit-server'
include 'conduit-commons'
include 'conduit-config'

include 'conduit-config-persistence'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did you decide to create an other module and not put it in conduit-config?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so that the json to pojo codegen can be isolated in a single package and then universally consumed externally.

cgardens added a commit that referenced this pull request Aug 12, 2020
In response to feedback on this PR #17 and after fiddling around with what implementing some endpoints looks like, I've made two updates to the configuration persistence:

* The whole class is synchronized, to try to avoid any concurrency issues in the MVP.
* Added a couple exception to the persistence interface. The philosophy I used here was that
    * we expose named exceptions that are actionable to the user. e.g. config not found, or you are trying to insert or access a config that does not pass validation.
    * we do NOT expose named exceptions related to the internal of the database (e.g. data corruption or we can't access the disk). we let these get handled as runtime exceptions.
@sbjorn sbjorn mentioned this pull request Aug 29, 2022
18 tasks
c-p-b pushed a commit that referenced this pull request Feb 19, 2023
@avirajsingh7 avirajsingh7 mentioned this pull request Aug 3, 2023
4 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants