conductor-oss--conductor
a9cd7750f4
CI / unit-test (push) Has been cancelled
CI / detect-changes (push) Has been cancelled
CI / build (push) Has been cancelled
Publish docs via GitHub Pages / Deploy docs (push) Has been cancelled
CI / test-harness (push) Has been cancelled
CI / generate-e2e-matrix (push) Has been cancelled
CI / e2e (push) Has been cancelled
CI / build-ui (push) Has been cancelled
Release Drafter / update_release_draft (push) Has been cancelled
UI v2 Integration CI / E2E (Integration) (push) Has been cancelled
UI v2 CI / Lint, Format & Test (push) Has been cancelled
UI v2 CI / E2E (Mocked) (push) Has been cancelled
258 行
7.9 KiB
Markdown
258 行
7.9 KiB
Markdown
# JDBC Configuration
|
|
|
|
This document describes the configuration format for JDBC database connections in Conductor.
|
|
|
|
## Overview
|
|
|
|
Conductor supports configuring **multiple named JDBC instances** for use by the `JDBC` worker task. This allows you to:
|
|
|
|
- Connect to multiple databases (MySQL, PostgreSQL, Oracle, etc.)
|
|
- Separate environments (prod, dev, staging)
|
|
- Use different connection pool settings per use case (read-heavy vs write-heavy)
|
|
|
|
## Configuration Format
|
|
|
|
JDBC instances are configured using a list-based approach under `conductor.jdbc.instances`:
|
|
|
|
```yaml
|
|
conductor:
|
|
jdbc:
|
|
instances:
|
|
- name: "instance-name" # Unique identifier for this instance
|
|
connection: # Connection configuration
|
|
datasourceURL: "jdbc:..." # JDBC connection URL
|
|
jdbcDriver: "..." # JDBC driver class (optional, auto-detected from URL)
|
|
user: "..." # Database username
|
|
password: "..." # Database password
|
|
# ... pool settings
|
|
```
|
|
|
|
## Configuration Examples
|
|
|
|
### Single MySQL Instance
|
|
|
|
```yaml
|
|
conductor:
|
|
jdbc:
|
|
instances:
|
|
- name: "mysql-prod"
|
|
connection:
|
|
datasourceURL: "jdbc:mysql://prod-db:3306/myapp"
|
|
jdbcDriver: "com.mysql.cj.jdbc.Driver"
|
|
user: "conductor"
|
|
password: "secret"
|
|
maximumPoolSize: 20
|
|
minimumIdle: 5
|
|
```
|
|
|
|
### Multiple Instances
|
|
|
|
```yaml
|
|
conductor:
|
|
jdbc:
|
|
instances:
|
|
- name: "mysql-prod"
|
|
connection:
|
|
datasourceURL: "jdbc:mysql://prod-db:3306/myapp"
|
|
jdbcDriver: "com.mysql.cj.jdbc.Driver"
|
|
user: "conductor"
|
|
password: "prod-secret"
|
|
maximumPoolSize: 20
|
|
|
|
- name: "postgres-analytics"
|
|
connection:
|
|
datasourceURL: "jdbc:postgresql://analytics-db:5432/warehouse"
|
|
user: "analyst"
|
|
password: "analytics-secret"
|
|
maximumPoolSize: 10
|
|
|
|
- name: "mysql-staging"
|
|
connection:
|
|
datasourceURL: "jdbc:mysql://staging-db:3306/myapp"
|
|
jdbcDriver: "com.mysql.cj.jdbc.Driver"
|
|
user: "conductor"
|
|
password: "staging-secret"
|
|
maximumPoolSize: 5
|
|
minimumIdle: 1
|
|
```
|
|
|
|
## Usage in Workflows
|
|
|
|
When using the JDBC task in your workflows, reference the instance by its configured name using `connectionId`:
|
|
|
|
```json
|
|
{
|
|
"name": "query_users",
|
|
"taskReferenceName": "query_users_ref",
|
|
"type": "JDBC",
|
|
"inputParameters": {
|
|
"connectionId": "mysql-prod",
|
|
"type": "SELECT",
|
|
"statement": "SELECT id, name, email FROM users WHERE status = ?",
|
|
"parameters": ["active"]
|
|
}
|
|
}
|
|
```
|
|
|
|
### SELECT Example
|
|
|
|
```json
|
|
{
|
|
"name": "find_orders",
|
|
"taskReferenceName": "find_orders_ref",
|
|
"type": "JDBC",
|
|
"inputParameters": {
|
|
"connectionId": "postgres-analytics",
|
|
"type": "SELECT",
|
|
"statement": "SELECT order_id, total FROM orders WHERE customer_id = ?",
|
|
"parameters": ["${workflow.input.customerId}"]
|
|
}
|
|
}
|
|
```
|
|
|
|
Output:
|
|
```json
|
|
{
|
|
"result": [
|
|
{"order_id": 101, "total": 49.99},
|
|
{"order_id": 205, "total": 129.50}
|
|
]
|
|
}
|
|
```
|
|
|
|
### UPDATE Example
|
|
|
|
```json
|
|
{
|
|
"name": "update_status",
|
|
"taskReferenceName": "update_status_ref",
|
|
"type": "JDBC",
|
|
"inputParameters": {
|
|
"connectionId": "mysql-prod",
|
|
"type": "UPDATE",
|
|
"statement": "UPDATE orders SET status = ? WHERE order_id = ?",
|
|
"parameters": ["shipped", "${workflow.input.orderId}"],
|
|
"expectedUpdateCount": 1
|
|
}
|
|
}
|
|
```
|
|
|
|
Output:
|
|
```json
|
|
{
|
|
"update_count": 1
|
|
}
|
|
```
|
|
|
|
If the actual update count does not match `expectedUpdateCount`, the transaction is rolled back and the task fails.
|
|
|
|
## Connection Configuration Options
|
|
|
|
| Property | Type | Default | Description |
|
|
|----------|------|---------|-------------|
|
|
| `datasourceURL` | String | Required | JDBC connection URL |
|
|
| `jdbcDriver` | String | Auto-detected | JDBC driver class name |
|
|
| `user` | String | Optional | Database username |
|
|
| `password` | String | Optional | Database password |
|
|
| `maximumPoolSize` | Integer | 32 | Maximum connections in the pool |
|
|
| `minimumIdle` | Integer | 2 | Minimum idle connections |
|
|
| `idleTimeoutMs` | Long | 30000 | Idle connection timeout (ms) |
|
|
| `connectionTimeout` | Long | 30000 | Connection acquisition timeout (ms) |
|
|
| `leakDetectionThreshold` | Long | 60000 | Leak detection threshold (ms) |
|
|
| `maxLifetime` | Long | 1800000 | Maximum connection lifetime (ms) |
|
|
|
|
## Migration from Old Configuration
|
|
|
|
### Old Format
|
|
|
|
```properties
|
|
conductor.worker.jdbc.connectionIds=mysql,postgres
|
|
conductor.worker.jdbc.mysql.connectionURL=jdbc:mysql://localhost:3306/db
|
|
conductor.worker.jdbc.mysql.driverClassName=com.mysql.cj.jdbc.Driver
|
|
conductor.worker.jdbc.mysql.username=root
|
|
conductor.worker.jdbc.mysql.password=secret
|
|
conductor.worker.jdbc.mysql.maximum-pool-size=10
|
|
|
|
conductor.worker.jdbc.postgres.connectionURL=jdbc:postgresql://localhost:5432/db
|
|
conductor.worker.jdbc.postgres.driverClassName=org.postgresql.Driver
|
|
conductor.worker.jdbc.postgres.username=pguser
|
|
conductor.worker.jdbc.postgres.password=pgpass
|
|
```
|
|
|
|
### New Format
|
|
|
|
```yaml
|
|
conductor:
|
|
jdbc:
|
|
instances:
|
|
- name: "mysql"
|
|
connection:
|
|
datasourceURL: "jdbc:mysql://localhost:3306/db"
|
|
jdbcDriver: "com.mysql.cj.jdbc.Driver"
|
|
user: "root"
|
|
password: "secret"
|
|
maximumPoolSize: 10
|
|
|
|
- name: "postgres"
|
|
connection:
|
|
datasourceURL: "jdbc:postgresql://localhost:5432/db"
|
|
jdbcDriver: "org.postgresql.Driver"
|
|
user: "pguser"
|
|
password: "pgpass"
|
|
```
|
|
|
|
**Note:** The old `conductor.worker.jdbc.*` format is still supported for backwards compatibility. If no `conductor.jdbc.instances` are configured, the system automatically falls back to reading the legacy format. The old and new formats are mutually exclusive -- if new-format instances are found, the legacy format is ignored.
|
|
|
|
### Property Name Mapping
|
|
|
|
| Old Property | New Property |
|
|
|---|---|
|
|
| `connectionURL` | `datasourceURL` |
|
|
| `driverClassName` | `jdbcDriver` |
|
|
| `username` | `user` |
|
|
| `password` | `password` |
|
|
| `maximum-pool-size` | `maximumPoolSize` |
|
|
| `idle-timeout-ms` | `idleTimeoutMs` |
|
|
| `minimum-idle` | `minimumIdle` |
|
|
|
|
## Best Practices
|
|
|
|
1. **Use descriptive names**: Choose instance names that clearly indicate their purpose (e.g., `mysql-prod`, `postgres-analytics`, `oracle-reporting`)
|
|
|
|
2. **Separate read/write pools**: For high-throughput systems, configure separate instances for read and write operations with appropriate pool sizes
|
|
|
|
3. **Right-size connection pools**: Set `maximumPoolSize` based on your database capacity and workload. A common formula is `connections = (core_count * 2) + effective_spindle_count`
|
|
|
|
4. **Enable leak detection**: The default `leakDetectionThreshold` of 60 seconds logs warnings for connections held longer than expected
|
|
|
|
5. **Use parameterized queries**: Always use `?` placeholders with the `parameters` list instead of string concatenation to prevent SQL injection
|
|
|
|
6. **Set expectedUpdateCount**: For critical UPDATE/INSERT/DELETE operations, set `expectedUpdateCount` to automatically rollback if the affected row count doesn't match
|
|
|
|
## Troubleshooting
|
|
|
|
### Instance Not Found
|
|
|
|
If you see "JDBC instance not found: xyz", check:
|
|
|
|
1. The `connectionId` in your workflow matches the configured `name` exactly
|
|
2. The instance is properly configured in your application.yml/properties
|
|
3. The application has been restarted after configuration changes
|
|
|
|
### Connection Timeout
|
|
|
|
If connections are timing out:
|
|
|
|
1. Verify network connectivity to the database
|
|
2. Check `connectionTimeout` value (default 30 seconds)
|
|
3. Ensure the connection pool is not exhausted (increase `maximumPoolSize` if needed)
|
|
4. Check database max connections limit
|
|
|
|
### Connection Leaks
|
|
|
|
If you see leak detection warnings:
|
|
|
|
1. Ensure all connections are properly closed (the JDBC worker handles this automatically)
|
|
2. If using custom integrations, wrap connection usage in try-with-resources
|
|
3. Review `leakDetectionThreshold` setting
|