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

External service #1074

Merged
merged 1 commit into from
Nov 30, 2023
Merged

External service #1074

merged 1 commit into from
Nov 30, 2023

Conversation

snkas
Copy link
Contributor

@snkas snkas commented Nov 28, 2023

External service concept is added. In order to have small PRs rather than large, this is the first with basic functionality for external services.

This PR encompasses:

  • Database table: service
  • Basic database operations for external services (list, create, get, update, delete)
  • API endpoints for basic operations on external services
  • Corresponding Python API generated
  • Database proptests
  • API integration tests

Is this a user-visible change (yes/no): yes

Copy link
Collaborator

@lalithsuresh lalithsuresh left a comment

Choose a reason for hiding this comment

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

Great start! Could you also integrate ExternalService into the src/db/test.rs?


/// An external service's configuration.
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, ToSchema)]
pub enum ExternalServiceConfig {
Copy link
Collaborator

Choose a reason for hiding this comment

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

If the type is already called ExternalService, you don't need to also repeat the prefix in the inner *Config types.

Copy link
Contributor Author

@snkas snkas Nov 29, 2023

Choose a reason for hiding this comment

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

Inlined them into the Service enumeration OpenAPI Python did not like that, instead using explicit types MysqlConfig and PostgresConfig

CREATE TABLE IF NOT EXISTS external_service (
id uuid PRIMARY KEY, -- Unique identifier (used primarily for foreign key relations)
tenant_id uuid NOT NULL, -- Tenant the external service belongs to
name varchar NOT NULL, -- Immutable unique name given by the tenant (e.g., mysql-example) used to refer to it in the API
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is it already immutable in our API?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, the PATCH /external_services/id endpoint only allows updating description and 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.

We could also enforce it in the database with a trigger potentially (?)

crates/pipeline_manager/src/api.rs Outdated Show resolved Hide resolved
crates/pipeline_manager/src/db/mod.rs Outdated Show resolved Hide resolved
@lalithsuresh
Copy link
Collaborator

lalithsuresh commented Nov 29, 2023

Bikeshed

@ryzhyk @gz regarding the API entity's name, we have ExternalService for now. Any other suggestions?
@snkas and I think it's precise, but it's kind of long.

@ryzhyk
Copy link
Contributor

ryzhyk commented Nov 29, 2023

ExternalServide seems adequate. The External prefix could be dropped without introducing ambiguity.

@lalithsuresh
Copy link
Collaborator

I'd be okay changing it to Service. A bit overloaded, but clean.

@snkas
Copy link
Contributor Author

snkas commented Nov 29, 2023

Changing name to Service

@snkas
Copy link
Contributor Author

snkas commented Nov 29, 2023

I've rebased with main, incorporated feedback (see comments) and implemented the test database.

  • Which services do we add at the start? I've temporarily added MysqlConfig and PostgresConfig as the two services currently implemented. In the future these current services might change (remove user/password for instance).
  • I'm planning to implement a few API tests, possibly in python/test.py or somewhere similar; EDIT: and as well in the integration tests
  • Should I also add a custom database test? Beyond the automated proptests currently done.

After this PR it might be also time to make MaybeSecretRef an API object? As it will likely be used in the services.

@lalithsuresh
Copy link
Collaborator

I've rebased with main, incorporated feedback (see comments) and implemented the test database.

* Which services do we add at the start? I've temporarily added MysqlConfig and PostgresConfig as the two services currently implemented. In the future these current services might change (remove user/password for instance).

It's more important to start with Kafka (let's start from all the services we use for connectors). So MySQL and Kafka would be the two important ones to start with. I don't think we need Postgres yet.

* I'm planning to implement a few API tests, possibly in `python/test.py` or somewhere similar; EDIT: and as well in the integration tests

It's probably better to add external tests like python API tests after you integrate with connectors. As such, there's no external workflow we can support with this PR that depends on services being configured correctly.

* Should I also add a custom database test? Beyond the automated proptests currently done.

The proptests should do.

After this PR it might be also time to make MaybeSecretRef an API object? As it will likely be used in the services.

Let's get the connector integration working first.

if modified_rows == 0 {
Err(DBError::UnknownService { service_id })
} else {
assert_eq!(modified_rows, 1);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Log this as an error. Don't assert outside tests.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Changed to:

if modified_rows != 1 {
    error!("More than one row ({modified_rows}) was modified when updating service {service_id}");
}

Copy link
Collaborator

Choose a reason for hiding this comment

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

Why not return an error in this case? This looks like it should not happen.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Changed to:

if modified_rows > 0 {
    Ok(())
} else {
    Err(DBError::UnknownService { service_id })
}

@snkas snkas force-pushed the external-service branch 2 times, most recently from 9e74c9b to 01067a1 Compare November 30, 2023 12:47
@snkas
Copy link
Contributor Author

snkas commented Nov 30, 2023

Rebased with main, incorporated feedback (removed assert and replaced Postgres service with Kafka service), added basic service integration test in integration_test.rs


/// A service's configuration.
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "snake_case")]
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why is the snake_case required?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added:
// snake_case such that the enumeration variants are not capitalized in (de-)serialization

Adds the Service type with basic functionality to the pipeline-manager.

This encompasses:
- Database table: service
- Basic database operations (list, create, get, update, delete)
- API endpoints
- Corresponding generated Python API
- Database proptests
- API integration test

Signed-off-by: Simon Kassing <simon.kassing@feldera.com>
@snkas snkas merged commit e8f4fd1 into main Nov 30, 2023
5 checks passed
@snkas snkas deleted the external-service branch November 30, 2023 19:08
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.

None yet

3 participants