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

Upgrade to Citus 12 #6611

Merged
merged 35 commits into from
Aug 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
25208ed
citus-12 upgrade
jnels124 Aug 8, 2023
0896f53
checkpoint
jnels124 Aug 8, 2023
07caa8e
working version
jnels124 Aug 10, 2023
f442d2c
* update docker image and doc
jnels124 Aug 10, 2023
c20cea0
* implement retry
jnels124 Aug 10, 2023
4e71776
fix typo
jnels124 Aug 10, 2023
4a3d94b
fix issue with different id parition intervals
jnels124 Aug 11, 2023
efa39da
use function to update table name
jnels124 Aug 11, 2023
5f44998
update doc for building citus image
jnels124 Aug 11, 2023
18c9dd6
utilize udf
jnels124 Aug 11, 2023
fc8515b
fix typo
jnels124 Aug 11, 2023
539ca96
remove maintenance service in favor of sql
jnels124 Aug 12, 2023
f826e6f
convert udf to procedure
jnels124 Aug 12, 2023
a87591a
update image registry
jnels124 Aug 12, 2023
7bb66de
Merge remote-tracking branch 'origin/main' into citus-12
jnels124 Aug 12, 2023
78297a9
fix test
jnels124 Aug 12, 2023
22b0040
add leader annotation
jnels124 Aug 13, 2023
df0ee5a
use interval for end date calc
jnels124 Aug 13, 2023
1351112
fix rest tests
jnels124 Aug 13, 2023
72ac11e
update docs. add unit test
jnels124 Aug 15, 2023
fee977a
address pr comments
jnels124 Aug 16, 2023
1070ed7
Merge remote-tracking branch 'origin/main' into citus-12
jnels124 Aug 16, 2023
286e71c
add missing annotation
jnels124 Aug 16, 2023
72bf1db
add range partition udf
jnels124 Aug 17, 2023
75ffafa
fix tests
jnels124 Aug 17, 2023
1f3ad04
update to work with additional partition column types
jnels124 Aug 17, 2023
f7cf45f
update test config
jnels124 Aug 17, 2023
a74dafa
Merge remote-tracking branch 'origin/main' into citus-12
jnels124 Aug 17, 2023
3626210
fix tests
jnels124 Aug 17, 2023
3779577
address pr feedback
jnels124 Aug 18, 2023
67281c1
move casts + udfs to migration script
jnels124 Aug 18, 2023
32ec3ab
address pr comments
jnels124 Aug 18, 2023
542dfb7
add missing file
jnels124 Aug 18, 2023
94f12ae
Merge remote-tracking branch 'origin/main' into citus-12
jnels124 Aug 18, 2023
77db579
cleanup
jnels124 Aug 21, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion charts/hedera-mirror/ci/v2-values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ graphql:
defaultAccount: 111146
importer:
env:
SPRING_FLYWAY_PLACEHOLDERS_IDPARTITIONSIZE: "1000000000000000"
SPRING_FLYWAY_PLACEHOLDERS_PARTITIONSTARTDATE: "(CURRENT_TIMESTAMP - '1970-01-01 00:00:00.000')"
steven-sheehy marked this conversation as resolved.
Show resolved Hide resolved
SPRING_FLYWAY_PLACEHOLDERS_PARTITIONTIMEINTERVAL: "'10 years'"
SPRING_FLYWAY_PLACEHOLDERS_SHARDCOUNT: "2"
SPRING_FLYWAY_PLACEHOLDERS_PARTITIONSTARTDATE: "'0 days'"
SPRING_PROFILES_ACTIVE: v2
# Ensure importer has time to start stream processing after startup
readinessProbe:
Expand Down
11 changes: 2 additions & 9 deletions charts/hedera-mirror/templates/secret-passwords.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -136,14 +136,7 @@ stringData:
coordinator-superuser.sql: |
-- Create extensions
create extension if not exists btree_gist;
create extension if not exists pg_cron;
create extension if not exists pg_stat_statements;
create schema if not exists partman authorization {{ $ownerUsername }};
create extension if not exists pg_partman schema partman;
alter schema partman owner to {{ $ownerUsername }};
grant all on schema partman to {{ $ownerUsername }};
grant usage on schema cron to {{ $ownerUsername }};
grant all on all tables in schema partman to {{ $ownerUsername }};
grant execute on all functions in schema partman to {{ $ownerUsername }};
grant execute on all procedures in schema partman to {{ $ownerUsername }};
-- give owner permission to create casts against timestamptz
alter type timestamptz owner to {{ $ownerUsername }};
{{- end -}}
12 changes: 3 additions & 9 deletions charts/hedera-mirror/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,6 @@ stackgres:
citus.executor_slow_start_interval: "100ms"
citus.max_cached_conns_per_worker: "4"
citus.max_shared_pool_size: "380"
cron.database_name: "{{ .Values.db.name }}"
log_checkpoints: "true"
log_timezone: "Etc/UTC"
max_connections: "300"
Expand All @@ -278,7 +277,6 @@ stackgres:
password_encryption: "scram-sha-256"
random_page_cost: "1.1"
shared_buffers: "12GB"
shared_preload_libraries: pg_cron,pg_partman_bgw
work_mem: "32MB"
instances: 1
resources:
Expand All @@ -288,12 +286,10 @@ stackgres:
size: 5Gi
enabled: false
extensions:
- name: citus
version: "12.0-1"
- name: btree_gist
version: stable
- name: pg_cron
version: stable
- name: pg_partman
version: "4.7.3"
nameOverride: citus
pgbouncer:
default_pool_size: "1000"
Expand All @@ -303,12 +299,11 @@ stackgres:
max_user_connections: "0"
pool_mode: session
podAntiAffinity: true
postgresVersion: 14
postgresVersion: 15
prometheus: false
worker:
config:
checkpoint_timeout: "1800"
cron.database_name: "{{ .Values.db.name }}"
log_checkpoints: "true"
log_timezone: "Etc/UTC"
max_connections: "400"
Expand All @@ -318,7 +313,6 @@ stackgres:
password_encryption: "scram-sha-256"
random_page_cost: "1.1"
shared_buffers: "12GB"
shared_preload_libraries: pg_cron,pg_partman_bgw
work_mem: "32MB"
instances: 1
replicasPerInstance: 1
Expand Down
2 changes: 1 addition & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
version: "3.7"
services:
citus:
image: mirrornodeswirldslabs/citus:11.2.0-alpine
image: gcr.io/mirrornode/citus:12.0.0
deploy:
replicas: 0
environment:
Expand Down
299 changes: 150 additions & 149 deletions docs/configuration.md

Large diffs are not rendered by default.

78 changes: 23 additions & 55 deletions docs/importer/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,63 +77,28 @@ For local testing the importer can be run using the following command:
./gradlew :importer:bootRun --args='--spring.profiles.active=v2'
```

## Building the Citus docker images
Two images are created, manually as needed, and pushed to our [Docker Hub repository](https://hub.docker.com/repository/docker/mirrornodeswirldslabs/citus/general).
An enhanced Citus debian base image (amd64) is used to run Citus/Postgres in production and other environments in GCP.
In addition, a multi-platform alpine linux image is built in order to be used for local testing (arm64 on M-series Macs) and
Github CI workflows (amd64).
## Building the Citus docker image
The citus image is built and then pushed to our [Google Cloud Registry](https://gcr.io/mirrornode).
A multi-platform alpine linux image is built in order to be used for local testing (arm64 on M-series Macs).
This image will need to be maintained until the [upstream builder](https://github.com/citusdata/docker/tree/master)
provides a multi-platform build supporting arm64.

`DockerFile`s to build a custom image to be used in v2 is located in the following folder:
```hedera-mirror-node/hedera-mirror-importer/src/main/resources/db/scripts/v2/docker```
In production and ci environments, citus is enabled through stackgres SGShardedCluster and doesn't use the custom image.

### Docker Hub details
The `mirrornodeswirldslabs` user was created just for this purpose. Therefore, when building the images below,
the tag contains `mirrornodeswirldslabs/citus` to indicate this repository, to which these images are later pushed.
`DockerFile` to build a custom image to be used in v2 testing is located in [Citus's upstream repository](https://github.com/citusdata/docker). To build this image:

The shared `mirrornode` 1Password vault contains the credentials for the Docker Hub `mirrornodeswirldslabs` user. This includes
an access token for the CLI as well as the TOTP configuration for MFA. You can use this to authenticate with
Docker Hub:
### GCR details
You authenticate with the registry via gcloud:

```console
docker login --username mirrornodeswirldslabs 1 ↵
Password:
gcloud auth configure-docker gcr.io
```
Copy and paste the token from 1Password.
You should see output similar to:
```console
Login Succeeded

Logging in with your password grants your terminal complete access to your account.
For better security, log in with a limited-privilege personal access token. Learn more at https://docs.docker.com/go/access-tokens/
```
**NOTE:** Not sure why it still issues the above message when using the token instead of the password. It is a complete
access token though.

If you instead see this:
```console
Error saving credentials: error storing credentials - err: exit status 1, out: `ID hub token does not contain email`
```
You may need to restart Docker Desktop according to this [forum post](https://forums.docker.com/t/id-hub-token-does-not-contain-email/134608/2).

### Debian

The `debian` subdirectory contains the `Dockerfile` which defines the image used in production and other GCP based environments.
The Debian image is based directly on the Citus Debian image with a couple of additional Postgres extensions installed;
cron and partman. The resultant image is built only for the amd64 platform architecture. The standard `docker build`
command can be used to accomplish this.

The database name to be used by citus can be provided using an environment variable as follows:

```console
docker build --build-arg DB=mirror_node --platform linux/amd64 -t mirrornodeswirldslabs/citus:11.2.0 .
Adding credentials for: gcr.io
```

### Alpine

The `alpine` subdirectory contains the `Dockerfile` used to build the Citus image for use for both local development
on an M-series Mac (arm64) as well in the Github CI workflows (amd64). Thus, this image is built for both platform
architectures on top of a Postgres alpine base image. Citus and the additional Postgres extensions are compiled from
source code as part of this docker image build. Citus does not yet provide an image for arm64.

### Build
The instructions here pertain to building the multi-platform alpine image on an M-series Mac using Docker Desktop. Please refer to
[Multi-platform images](https://docs.docker.com/build/building/multi-platform/) for an overview on how to use Docker
Desktop to do this.
Expand All @@ -151,12 +116,19 @@ mybuilder

Switch to the new builder:
```console
$ docker buildx use mybuilder
docker buildx use mybuilder
```

Checkout the upstream project containing the docker file
```
git clone git@github.com:citusdata/docker.git
cd docker
```

Build the image for both amd64 (Github CI) and arm64 (local testing). Don't forget the '.' at the end of the line. This
can take some time depending on your internet speed. You will see activity around both arm64 and amd64.
```console
$ docker buildx build --build-arg DB=mirror_node --platform linux/arm64,linux/amd64 -t mirrornodeswirldslabs/citus:11.2.0-alpine .
$ docker buildx build --platform linux/arm64,linux/amd64 -t gcr.io/mirrornode/citus:12.0.0 --file alpine/Dockerfile .
[+] Building 351.1s (28/28) FINISHED
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
Expand All @@ -175,11 +147,7 @@ rather than as a separate step below.

If you did not utilize `--push` with `docker buildx` when building the alpine image, push it now to Docker Hub.
```console
docker push mirrornodeswirldslabs/citus:11.2.0-alpine
```
And for debian:
```console
docker push mirrornodeswirldslabs/citus:11.2.0
docker push gcr.io/mirrornode/citus:12.0.0
```
You can then see that the images have been updated in [the repository](https://hub.docker.com/repository/docker/mirrornodeswirldslabs/citus/general).
If you click on the tags you can see the OS/ARCH supported by each.
9 changes: 5 additions & 4 deletions hedera-mirror-graphql/src/test/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,13 @@ spring:
chunkIdInterval: 10000
chunkTimeInterval: 604800000000000
compressionAge: 9223372036854775807 # use long max to avoid compression during test
cronSchedule: "'@daily'"
db-name: ${hedera.mirror.graphql.db.name}
db-user: ${hedera.mirror.graphql.db.username}
partitionIdInterval: "'1000000'"
partitionStartDate: "'0 days'"
partitionTimeInterval: "'1 year'"
idPartitionSize: 1000000000000000
maxEntityId: 5000000
maxEntityIdRatio: 2.0
partitionStartDate: "(CURRENT_TIMESTAMP - '1970-01-01 00:00:00.000')"
partitionTimeInterval: "'10 years'"
schema: public
shardCount: 2
topicRunningHashV2AddedTimestamp: 0
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
embedded:
postgresql:
docker-image: mirrornodeswirldslabs/citus:11.2.0-alpine
docker-image: gcr.io/mirrornode/citus:12.0.0
initScriptPath: db/init-v2.sql
spring:
flyway:
Expand Down
10 changes: 1 addition & 9 deletions hedera-mirror-graphql/src/test/resources/db/init-v2.sql
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,7 @@ create schema if not exists public authorization mirror_node;
-- Partition privileges
grant connect on database mirror_node to readwrite;
grant all privileges on database mirror_node to mirror_node;
create extension if not exists pg_cron;
create schema if not exists partman authorization mirror_node;
create extension if not exists pg_partman schema partman;
alter schema partman owner to mirror_node;
grant create on database mirror_node to mirror_node;
grant all on schema partman to mirror_node;
grant usage on schema cron to mirror_node;
grant all on all tables in schema partman to mirror_node;
grant execute on all functions in schema partman to mirror_node;
grant execute on all procedures in schema partman to mirror_node;
grant all on schema public to mirror_node;
grant temporary on database mirror_node to mirror_node;
alter type timestamptz owner to mirror_node;
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,13 @@ spring:
chunkIdInterval: 10000
chunkTimeInterval: 604800000000000
compressionAge: 9223372036854775807 # use long max to avoid compression during test
cronSchedule: "'@daily'"
db-name: ${hedera.mirror.grpc.db.name}
db-user: ${hedera.mirror.grpc.db.username}
partitionIdInterval: "'1000000000'"
partitionStartDate: "'0 days'"
partitionTimeInterval: "'1 year'"
idPartitionSize: 1000000000000000
maxEntityId: 5000000
maxEntityIdRatio: 2.0
partitionStartDate: "(CURRENT_TIMESTAMP - '1970-01-01 00:00:00.000')"
partitionTimeInterval: "'10 years'"
schema: public
shardCount: 2
topicRunningHashV2AddedTimestamp: 0
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
embedded:
postgresql:
docker-image: mirrornodeswirldslabs/citus:11.2.0-alpine
docker-image: gcr.io/mirrornode/citus:12.0.0
initScriptPath: db/scripts/init-v2.sql
spring:
flyway:
Expand Down
10 changes: 1 addition & 9 deletions hedera-mirror-grpc/src/test/resources/db/scripts/init-v2.sql
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,7 @@ create schema if not exists public authorization mirror_node;
-- Partition privileges
grant connect on database mirror_node to readwrite;
grant all privileges on database mirror_node to mirror_node;
create extension if not exists pg_cron;
create schema if not exists partman authorization mirror_node;
create extension if not exists pg_partman schema partman;
alter schema partman owner to mirror_node;
grant create on database mirror_node to mirror_node;
grant all on schema partman to mirror_node;
grant usage on schema cron to mirror_node;
grant all on all tables in schema partman to mirror_node;
grant execute on all functions in schema partman to mirror_node;
grant execute on all procedures in schema partman to mirror_node;
grant all on schema public to mirror_node;
grant temporary on database mirror_node to mirror_node;
alter type timestamptz owner to mirror_node;
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package com.hedera.mirror.importer.config;

import com.hedera.mirror.importer.db.DBProperties;
import com.zaxxer.hikari.HikariDataSource;
import javax.sql.DataSource;
import org.springframework.boot.autoconfigure.jdbc.JdbcProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
Expand All @@ -37,15 +38,21 @@ JdbcTemplate jdbcTemplate(DataSource dataSource, JdbcProperties properties) {
@Bean
@Owner
JdbcTemplate jdbcTemplateOwner(DBProperties dbProperties, JdbcProperties properties) {
String jdbcUrl = String.format(
return createJdbcTemplate(createDataSource(dbProperties), properties);
}

HikariDataSource createDataSource(DBProperties dbProperties) {
var jdbcUrl = String.format(
"jdbc:postgresql://%s:%d/%s?tcpKeepAlive=true",
dbProperties.getHost(), dbProperties.getPort(), dbProperties.getName());
var datasource = DataSourceBuilder.create()
var dataSource = DataSourceBuilder.create()
.password(dbProperties.getOwnerPassword())
.url(jdbcUrl)
.username(dbProperties.getOwner())
.type(HikariDataSource.class)
.build();
return createJdbcTemplate(datasource, properties);
dataSource.setConnectionInitSql(dbProperties.getConnectionInitSql());
return dataSource;
}

private JdbcTemplate createJdbcTemplate(DataSource dataSource, JdbcProperties properties) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
@Validated
@ConfigurationProperties("hedera.mirror.importer.db")
public class DBProperties {
private String connectionInitSql = "";

@NotBlank
private String host = "";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* Copyright (C) 2023 Hedera Hashgraph, LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.hedera.mirror.importer.db;

import com.google.common.base.Stopwatch;
import com.hedera.mirror.importer.config.Owner;
import com.hedera.mirror.importer.leader.Leader;
import jakarta.inject.Named;
import lombok.*;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.annotation.Profile;
import org.springframework.context.event.EventListener;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.retry.annotation.Retryable;
import org.springframework.scheduling.annotation.Scheduled;

@CustomLog

Check warning on line 31 in hedera-mirror-importer/src/main/java/com/hedera/mirror/importer/db/PartitionMaintenance.java

View check run for this annotation

Codecov / codecov/patch

hedera-mirror-importer/src/main/java/com/hedera/mirror/importer/db/PartitionMaintenance.java#L31

Added line #L31 was not covered by tests
@Named
@Profile("v2")
@RequiredArgsConstructor

Check warning on line 34 in hedera-mirror-importer/src/main/java/com/hedera/mirror/importer/db/PartitionMaintenance.java

View check run for this annotation

Codecov / codecov/patch

hedera-mirror-importer/src/main/java/com/hedera/mirror/importer/db/PartitionMaintenance.java#L34

Added line #L34 was not covered by tests
public class PartitionMaintenance {
private static final String RUN_MAINTENANCE_QUERY =
"""
CALL create_mirror_node_time_partitions();
CALL create_mirror_node_range_partitions();
""";

@Owner
private final JdbcTemplate jdbcTemplate;

@Scheduled(cron = "${hedera.mirror.importer.db.maintenance.cron:0 0 0 * * ?}")
@EventListener(ApplicationReadyEvent.class)
@Retryable
@Leader
public void runMaintenance() {
log.info("Running partition maintenance");
Stopwatch stopwatch = Stopwatch.createStarted();
jdbcTemplate.execute(RUN_MAINTENANCE_QUERY);
log.info("Partition maintenance completed successfully in {}", stopwatch);
}

Check warning on line 54 in hedera-mirror-importer/src/main/java/com/hedera/mirror/importer/db/PartitionMaintenance.java

View check run for this annotation

Codecov / codecov/patch

hedera-mirror-importer/src/main/java/com/hedera/mirror/importer/db/PartitionMaintenance.java#L50-L54

Added lines #L50 - L54 were not covered by tests
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,6 @@ public class CommonParserProperties {
@NotNull
private Collection<TransactionFilter> include = new ArrayList<>();

@Min(1)
private int tempTableBufferSize; // Default value set in application.yml, size in MB

@Getter(lazy = true)
private final Predicate<TransactionFilterFields> filter = includeFilter().and(excludeFilter());

Expand Down
Loading
Loading