Open Rail Association OSRD

repository·dev·Indexed 20 days ago

https://github.com/openrailassociation/osrd

A railway visualization and simulation project featuring a simulation backend, the ui-charts React library for spacetime charts and speed profiles, and the editoast toolset. Includes documentation for deploying via Helm to Kubernetes, building the simulation backend with Gradle, managing OpenFGA authorization migrations, and converting OpenStreetMap data to RailJSON format.

Tokens
60.7K
Snippets
203
Records
301
Agent score
70%

What's inside OSRD

  1. Understand OpenFGA migration behavior and limitations

    dev

    The current implementation of fga_migrations has the following characteristics:

    • Scope: Only authorization models can be migrated; tuple migrations are not yet supported.
    • Immutability: Applying a migration pushes a new authorization model to the OpenFGA store and sets it as the default. Because OpenFGA models are immutable, previous models are neither deleted nor altered.
    • Rollbacks: Since there are currently no tuples to migrate, rolling back to migration n, applying migration n, and running all migrations up to n are functionally identical operations.
  2. Handle 'mismatch between exploration and postprocessing' errors

    dev

    This error occurs when assumptions made during the exploration phase (e.g., finding an opening for a solution) are invalidated during post-processing (e.g., failing to converge to a conflict-free simulation).

    Common causes:

    1. Engineering allowances are impossible: Usually logged as a warning before the error.
    2. Inconsistent conflict detection: Differences in how incremental conflict detection or spacing requirement generation behaves between exploration and post-processing.
    3. Simulation input differences: During search, simulation inputs are limited to the simulated block (ignoring slopes from earlier blocks), whereas post-processing considers slopes from the entire area covered by the train.

    Debugging strategy:

    • Use conditional breakpoints at post-processing to identify the conflicting zone ID and the specific time.
    • Use conditional breakpoints during exploration to see how the search behaves.
    • Note that spacing requirement times are offset by the departure time after initial generation.
  3. Understand Route and Waypoint structures

    dev

    Routes in railjson_generator can be manually constructed or generated via InfraBuilder.generate_routes().

    Route Attributes:

    • waypoints: List[Waypoint]: The sequence of waypoints in the route.
    • release_waypoints: List[Waypoint]: Waypoints used for progressive release.
    • entry_point_direction: Direction: The direction at the start of the route.
    • switches_directions: Mapping[str, str]: Mapping of switch labels to directions.
    • label: str: The route identifier.
    • entry_point: A getter returning waypoints[0].
    • exit_point: A getter returning waypoints[-1].
  4. How the SpaceTimeChart component works

    dev

    The SpaceTimeChart is a React component used to visualize train paths.

    Key Characteristics:

    • Axes: By default, the horizontal axis (Ox) represents time and the vertical axis (Oy) represents space, though these can be swapped.
    • Rendering: Paths, graduations, and labels are rendered using canvas elements.
    • Interaction: Interaction detection is handled via a "picking" technique, where shapes are rendered on a separate layer with unique colors to detect user input.
    • State Management: The component is stateless. It is responsible only for rendering. You must manage all state (including paths, offsets, scales, and zoom levels) in the parent component and pass them down as props.
  5. Determine what to test: Unit vs Integration

    dev

    Decide the scope of your test based on the following criteria:

    Unit Tests

    • Scope: Test one function or method at a time.
    • Goal: Verify output based on input parameters.
    • Coverage: Test general cases (expected parameters), edge cases (unexpected parameters), and side effects (global variables, shared states).

    Integration Tests

    • Scope: Test functions managing application behavior, such as:
      • Application lifecycle management.
      • API calls.
      • Context variable management.
      • Store variable management.
      • Module/application orchestration.
    • Goal: Test parameters and side effects, but also verify behaviors during component mounting, updating, and unmounting.

    What NOT to test

    Avoid redundant tests. Do not test:

    • The framework (e.g., React).
    • External libraries.
    • The browser.
    • Unrelated logic (e.g., do not use an integration test to perform unit testing; in integration tests, the functions called by the unit under test should not be mocked).
  6. How ui-spacetimechart works

    dev

    The ui-spacetimechart is a React component used to visualize train paths on a spacetime chart where the horizontal axis (Ox) is time and the vertical axis (Oy) is space.

    Rendering Mechanism:

    • Canvas Rendering: Paths, graduations, and labels are rendered directly onto canvas elements for performance.
    • Interaction (Picking): To enable interaction detection, shapes are rendered on a separate layer using unique colors. This technique, known as "picking," allows the component to identify which shape was interacted with based on its color.

    State Management: ui-spacetimechart is a stateless rendering component. It does not manage any internal state. The parent component is responsible for managing and providing all state, including:

    • Paths
    • Offsets
    • Scales
    • Zoom levels
  7. Understand the osrd-ui versioning model

    dev

    The osrd-ui monorepo uses a unified versioning strategy:

    • Indivisible Releases: A version number represents a release of all subpackages together. Even if only one package (e.g., ui-icons) changes, a new release is issued for the entire set of packages.
    • Git Tag Driven: Version numbers are managed solely through Git tags (e.g., ui-vX.Y.Z).
    • Local Development Versions: Local package.json files are kept at version 0.0.1-dev to clearly identify them as development versions and avoid conflicts with real releases.
  8. Quickstart: Build and run the OSRD stack with Docker

    dev

    To compile and run the entire OSRD application stack with an example infrastructure, use Docker Compose.

    For Linux or WSL users: You can use ./osrd-compose host instead of docker compose to enable host networking, which is useful when launching services in a debugger.

    For macOS (Apple Silicon) users: To avoid slow amd64 emulation for Postgres/PostGIS, set the arm64 image name before running the compose command:

    export OSRD_POSTGIS_IMAGE='nickblah/postgis:16-postgis-3'
    docker compose up -d --build
    # build and run the entire stack
    docker compose up -d --build
  9. Write integration tests with React Testing Library

    dev

    For testing hooks and components, use React Testing Library (RTL).

    Standard Test Pattern

    1. Imports: Import dependencies and define common test data.
    2. Mock: Declare necessary mocks.
    3. Arrange: Instantiate the component via render or the hook via renderHook.
    4. Act: Perform actions on the component or hook methods (use act() to wrap actions requiring React lifecycle execution).
    5. Assert: Verify the output matches expectations.

    Testing Hooks

    • Use renderHook to test hooks.
    • Utilize the returned methods: render, rerender, and unmount.
    • Store Integration: If a hook requires the application store, use the project-specific helper renderHookWithStore imported from front/src/store/__tests__/index.ts.

    Mocking APIs

    To mock API calls without complex type gymnastics, import mockOsrdEditoastEndpoints from front/src/common/api/__mocks__/osrdEditoastApi.ts and use the provided endpoints.

  10. Run generation scripts

    dev

    You can run individual generation scripts by passing an output directory as the first argument. Alternatively, you can use the library helper to generate multiple infrastructures at once by providing a directory of data and a pattern for the scripts.

    Run a single script:

    mkdir small_infra_out
    uv run ../../tests/infra-scripts/small_infra.py small_infra_out

    Run multiple scripts at once:

    uv run -m railjson_generator ../../tests/data/infras ../../tests/infra-scripts/*.py
    uv run ../../tests/infra-scripts/small_infra.py small_infra_out
  11. Use development and debugging tools

    dev

    The following tools are recommended for maintaining code quality and formatting in the editoast project.

    Formatting and Linting

    • rustfmt: Format Rust code using cargo fmt --all. (Install via rustup component add rustfmt)
    • taplo: Format TOML files using taplo fmt. (Install via cargo install --locked taplo-cli)
    • clippy: Run the Rust linter using cargo clippy --workspace --all-features --all-targets -- -D warnings. (Install via rustup component add clippy)

    Debugging

    By default, the project strips debug information to speed up compilation. To debug, use the dev-for-debug profile:

    cargo build --profile dev-for-debug

    No-cache mode

    To prevent cached results from interfering with debugging, you can run the server with the EDITOAST_NO_CACHE environment variable set to true.

    # Run server without cache
    EDITOAST_NO_CACHE=true cargo run -- runserver
    
    # If using docker
    EDITOAST_NO_CACHE=true ./osrd-compose up -d