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

feat: config migration and graph repo client #1889

Draft
wants to merge 24 commits into
base: main
Choose a base branch
from

Conversation

MichaelsJP
Copy link
Member

Pull Request Checklist

  • 1. I have rebased the latest version of the main branch into my feature branch and all conflicts
    have been resolved.
  • 2. I have added information about the change/addition to functionality to the CHANGELOG.md file under the
    [Unreleased] heading.
  • 3. I have documented my code using JDocs tags.
  • 4. I have removed unnecessary commented out code, imports and System.out.println statements.
  • 5. I have written JUnit tests for any new methods/classes and ensured that they pass.
  • 6. I have created API tests for any new functionality exposed to the API.
  • 7. If changes/additions are made to the ors-config.json file, I have added these to the ors config documentation
    along with a short description of what it is for, and documented this in the Pull Request (below).
  • 8. I have built graphs with my code of the Heidelberg.osm.gz file and run the api-tests with all test passing
  • 9. I have referenced the Issue Number in the Pull Request (if the changes were from an issue).
  • 10. For new features or changes involving building of graphs, I have tested on a larger dataset
    (at least Germany), and the graphs build without problems (i.e. no out-of-memory errors).
  • 11. For new features or changes involving the graphbuilding process (i.e. changing encoders, updating the
    importer etc.), I have generated longer distance routes for the affected profiles with different options
    (avoid features, max weight etc.) and compared these with the routes of the same parameters and start/end
    points generated from the current live ORS.
    If there are differences then the reasoning for these MUST be documented in the pull request.
  • 12. I have written in the Pull Request information about the changes made including their intended usage
    and why the change was needed.
  • 13. For changes touching the API documentation, I have tested that the API playground renders correctly.

Fixes # .

Information about the changes

  • Key functionality added:
  • Reason for change:

Examples and reasons for differences between live ORS routes, and those generated from this pull request

Required changes to ors config (if applicable)

takb and others added 4 commits November 8, 2024 17:30
…ure into ors-engine

- The config is now entirely encapsulated in a clear class hierarchy that can be imported by any module needed. Ors-api imports those classes and is able to use them directly with the externalized spring-boot config loader functionality.
- The config classes are using jackson to deserialize yaml files. Since its the basic jackson logic, theoretically ors should understand all possible file formats jackson can handle (yml,json etc.). But we assume yml only.
- All formerly bare string accesses to config parameters are now clear function and method accesses from the config classes.
- The config class engine has a new parameter graphManagement for a new graph repo client which will be added in subsequent commits
- The config classes are currently not designed for serialization except the graph management configs.
- Some obvious generic getter/setter scenarios have now been implemented or replaced with the corresponding lombok imports.
- ProfileProperties and ProfileDefaultProperties have been merged. ProfileProperties has new parameters `build`, `repo`, and `service`. Except repo the other two include no new parameters, just moved ones. Repo is new and is part of the coming graph management feature.

Co-authored-by: jhaeu <[email protected]>
Co-authored-by: Julian Psotta <[email protected]>

BREAKING CHANGE: Structural changes in the configuration make this change incompatible with earlier versions and configurations.
…pository

- The feature allows ors to download graphs from a pre-defined remote repository. The ors client looks for specific things like graph version, the used profiles, area of interest etc. to decide which graph should be downloaded.
- To differentiate incompatible graphs, these changes are accommodated by a manually defined graph-version. Once a version is different, the graphs are incompatible.
- While building new graphs, the folder of the graphs will include YAML files that contain the settings the graphs were built with. This ensures that graphs cannot be loaded with different graph building relevant configs.
- Downloaded graphs will always contain these files.
- Graph download triggers can be configure by schedule as well as its activation.

Co-authored-by: Takara Baumbach <[email protected]>
Co-authored-by: Julian Psotta <[email protected]>
… with tests based on junit and TestContainers

The focus of these tests is not to check for correct API tests but for the correct interaction with external tools and dependencies:

- Config environment tests
- Config file tests
- Config lookup tests
- GeoTools temp folder creation test
- GraphRepoTests that mock an external graph repo with different scenarios

The new junit based integration tests are executed like any other junit tests. Under the hood they use test containers to spawn containers with docker to provide isolated and clear defined environments.

All tests run in the same way for all current relevant execution scenarios, maven/spring-boot, war/tomcat, java/jar and test for the same expected behavior.

All tests are executed in parallel. The max parallel tests are configured by `junit-platform.properties`. Before each parallel execution the container layers are built with a single thread to ensure that parallel tests reuse the same image layers for the containers. This leads to a massively reduced build time in general. Graphs are pre-built by the same layer caching process before the individual test run and shared among tests that request shared graphs.
Some tests require new graphs on the fly.

Co-authored-by: jhaeu <[email protected]>
Co-authored-by: Takara Baumbach <[email protected]>
The documentation now includes information for the new configuration of ors. The configuration is now differently structured and thus content moved a lot.

Additionally, the graph download functionality is described.

Co-authored-by: Takara Baumbach <[email protected]>
@MichaelsJP MichaelsJP changed the title Feat/graph repo client feat: graph repo client Nov 8, 2024
@MichaelsJP MichaelsJP changed the title feat: graph repo client feat: config migration and graph repo client Nov 8, 2024
@github-actions github-actions bot added feature and removed feature labels Nov 8, 2024
This was referenced Nov 8, 2024
@MichaelsJP MichaelsJP linked an issue Nov 8, 2024 that may be closed by this pull request
@MichaelsJP MichaelsJP removed a link to an issue Nov 8, 2024
jhaeu and others added 2 commits November 12, 2024 15:11
the latter is flaky because the format depends on local locale, time zone etc.
@sfendrich
Copy link
Contributor

The commit message title of commit 6035301 is irritating. A refactoring is not supposed to be a breaking change.

@TheGreatRefrigerator
Copy link
Contributor

The commit message title of commit 6035301 is irritating. A refactoring is not supposed to be a breaking change.

The ! indicates a breaking change & the body describes the thing that is breaking:

BREAKING CHANGE: Structural changes in the configuration make this change incompatible with earlier versions and configurations.

according to the specification we are currently using, that's how a breaking change should be committed and it can be on any commit type:
https://www.conventionalcommits.org/en/v1.0.0/#examples

Or do you think the actual title confusing?
refactor the config classes into a separate structure into ors-engine
Would you suggest a different one?

@sfendrich
Copy link
Contributor

No, I think that in general "refactor" and "BREAKING CHANGE" are incompatible by their definition. I wonder whether there are rare exceptions to this?
As the commit changes the behavior it is either a fix or a feat.

@TheGreatRefrigerator
Copy link
Contributor

ah due to refactoring being defined by "not altering existing functionality" 😓. Yeah, agreed.
How about:
feat(config)!: Move the config classes into a separate structure into ors-engine

Copy link
Contributor

@sfendrich sfendrich left a comment

Choose a reason for hiding this comment

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

This is only a partial review suggesting some improvements. The PR is too large to conduct a full review.

@@ -40,7 +40,7 @@
#ors.endpoints.matrix.maximum_routes_flexible=25
#ors.endpoints.matrix.maximum_visited_nodes=100000
#ors.endpoints.matrix.maximum_search_radius=2000
#ors.endpoints.matrix.u_turn_costs=-1
#ors.endpoints.matrix.u_turn_cost=-1
Copy link
Contributor

Choose a reason for hiding this comment

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

Why has this changed? We use the plural form of "costs" everywhere else.

prepareGreenIndexSlots();
ExtendedStorageProperties parameters;
try {
parameters = this.parameters;
Copy link
Contributor

Choose a reason for hiding this comment

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

How is this assignment supposed to fail? The same question applies to the other GraphStoragBuilders.

Copy link
Contributor

Choose a reason for hiding this comment

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

Why has the format been changed? I think XML was on purpose as the file is manually adapted to account for special test cases. XML would make it easier to inspect changes or add new changes for new tests.


@Configuration
@ConfigurationProperties(prefix = "ors.engine")
public class EngineProperties extends org.heigit.ors.config.EngineProperties {
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't like that the child class has the same name as the parent class.

@@ -24,6 +26,9 @@
import java.util.*;

public class IsochroneRequest extends ServiceRequest {
@Getter
@Setter
private String profileName;
Copy link
Contributor

Choose a reason for hiding this comment

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

Lombok should not be used here because:

  1. It reduces only a single getter/setter
  2. The usage of this field is semantically not a getter/setter

@@ -40,6 +42,9 @@
import org.locationtech.jts.geom.Coordinate;

public class MatrixRequest extends ServiceRequest {
@Getter
@Setter
private String profileName;
Copy link
Contributor

Choose a reason for hiding this comment

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

Lombok should not be used here because:

  1. It reduces only a single getter/setter
  2. The usage of this field is semantically not a getter/setter

@@ -31,55 +32,38 @@

public class GraphProcessContext {
private static final Logger LOGGER = Logger.getLogger(GraphProcessContext.class.getName());
private List<GraphBuilder> graphBuilders;
private GraphBuilder[] arrGraphBuilders;
@Getter
Copy link
Contributor

Choose a reason for hiding this comment

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

Lombok should not be used here because:

  1. It reduces only a single getter/setter
  2. The usage of this field is semantically not a getter/setter

private List<GraphStorageBuilder> storageBuilders;
private GraphStorageBuilder[] arrStorageBuilders;
private int trafficArrStorageBuilderLocation = -1;
@Getter
private final double maximumSpeedLowerBound;
Copy link
Contributor

Choose a reason for hiding this comment

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

Lombok should not be used here because:

  1. It reduces only a single getter/setter
  2. The usage of this field is semantically not a getter/setter

import org.locationtech.jts.geom.Coordinate;

public class SnappingRequest extends ServiceRequest {
@Getter
@Setter
private String profileName;
Copy link
Contributor

Choose a reason for hiding this comment

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

Lombok should not be used here because:

  1. It reduces only a single getter/setter
  2. The usage of this field is semantically not a getter/setter

Copy link
Contributor

@sfendrich sfendrich left a comment

Choose a reason for hiding this comment

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

Partial review.

@Scheduled(cron = "${ors.engine.graph_management.download_schedule:0 0 0 31 2 *}")//Default is "never"
public void checkForUpdatesInRepo() {

if (!enabled) {
Copy link
Contributor

Choose a reason for hiding this comment

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

could be null

}

public void checkForDownloadedGraphsToActivate(String trigger) {
if (!enabled) {
Copy link
Contributor

Choose a reason for hiding this comment

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

could be null

@Async
@Scheduled(fixedDelay = 1, timeUnit = TimeUnit.MINUTES)
public void repeatedGraphActivationAttempt() {
if (!enabled) {
Copy link
Contributor

Choose a reason for hiding this comment

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

could be null

if (!enabled) {
LOGGER.debug("Graph management is disabled, skipping scheduled repository check...");
return;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

We repeatedly have to check for being enabled. Shouldn't this be handled through polymorphism?

Copy link
Contributor

Choose a reason for hiding this comment

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

What makes this class and its child classes RepoManagers instead of Repos?

Copy link
Contributor

Choose a reason for hiding this comment

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

GraphInfo is a very generic name. Can we provide a better one that expresses the content of this class and its subclasses?

jhaeu and others added 9 commits November 22, 2024 12:02
Split the configuration documentation into two logical subpages.

Co-authored-by: Julian Psotta <[email protected]>
This commit truly isolates the integration tests scenarios. Before testcontainers would always randomly cache unrelated parts of the dockerfiles. With this setup it doesn't happen anymore and the CI workflow will be able to run way faster.
The new workflow first builds and caches the builder image. This image is big and clunky and would only increase the parallel test time massively. The testing graph is build in the same way. The image ID from the image is used to check compatibility with the graph. When all that works the integration tests are started in parallel for all scenarios and test classes.
The tests are too heavy to be run all the time. Let's limit them to PR and push on main
The integration tests are quite powerful but also more complex than usual tests. Hence, they need some deeper explanation.
This way all workflows now use the same caches.
Copy link

sonarcloud bot commented Nov 22, 2024

Quality Gate Failed Quality Gate failed

Failed conditions
E Reliability Rating on New Code (required ≥ A)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants