Skip to content
This repository has been archived by the owner on Apr 2, 2024. It is now read-only.

Commit

Permalink
Fix Promscale on TimescaleDB-OSS.
Browse files Browse the repository at this point in the history
Signed-off-by: Harkishen Singh <harkishensingh@hotmail.com>
  • Loading branch information
Harkishen-Singh committed Jul 19, 2021
1 parent f11b518 commit 04ddd3f
Show file tree
Hide file tree
Showing 14 changed files with 220 additions and 17 deletions.
14 changes: 8 additions & 6 deletions .github/workflows/go.yml
Expand Up @@ -106,11 +106,12 @@ jobs:
strategy:
matrix:
test-setups:
- {name: "Multinode", shortname: "multinode", ext: true, tsdb: true, tsdb2: true, multi: true, pg: 13}
- {name: "W/O Promscale Extension", shortname: "wo-prom-ext", ext: false, tsdb: true, tsdb2: true, multi: false, pg: 13}
- {name: "Plain Postgres", shortname: "plain-pg", ext: false, tsdb: false, tsdb2: false, multi: false, pg: 13}
- {name: "Timescaledb 1.x (pg 12)", shortname: "tsdb1x-pg-12", ext: true, tsdb: true, tsdb2: false, multi: false, pg: 12}
- {name: "Plain Postgres (12)", shortname: "plain-pg-12", ext: false, tsdb: false, tsdb2: false, multi: false, pg: 12}
- {name: "Multinode", shortname: "multinode", ext: true, tsdb: true, tsdb2: true, tsdboss: false, multi: true, pg: 13}
- {name: "W/O Promscale Extension", shortname: "wo-prom-ext", ext: false, tsdb: true, tsdb2: true, tsdboss: false, multi: false, pg: 13}
- {name: "Plain Postgres", shortname: "plain-pg", ext: false, tsdb: false, tsdb2: false, tsdboss: false, multi: false, pg: 13}
- {name: "Timescaledb 1.x (pg 12)", shortname: "tsdb1x-pg-12", ext: true, tsdb: true, tsdb2: false, tsdboss: false, multi: false, pg: 12}
- {name: "Plain Postgres (12)", shortname: "plain-pg-12", ext: false, tsdb: false, tsdb2: false, tsdboss: false, multi: false, pg: 12}
- {name: "TimescaleDB-OSS", shortname: "tsdb-oss", ext: false, tsdb: true, tsdb2: true, tsdboss: true, multi: false, pg: 13}
steps:

- name: Set up Go 1.14
Expand Down Expand Up @@ -145,8 +146,9 @@ jobs:
TSDB: ${{ matrix.test-setups.tsdb }}
TSDB2: ${{ matrix.test-setups.tsdb2 }}
MULTI: ${{ matrix.test-setups.multi }}
TSDBOSS: ${{ matrix.test-setups.tsdboss }}
SHORTNAME: ${{ matrix.test-setups.shortname }}
run: go test -race ./pkg/tests/end_to_end_tests/ -use-extension=$EXT -use-timescaledb=$TSDB -use-timescale2=$TSDB2 -use-multinode=$MULTI -postgres-version-major=$PG > $SHORTNAME-test-run.log 2>&1
run: go test -race ./pkg/tests/end_to_end_tests/ -use-extension=$EXT -use-timescaledb=$TSDB -use-timescale2=$TSDB2 -use-timescaledb-oss=$TSDBOSS -use-multinode=$MULTI -postgres-version-major=$PG > $SHORTNAME-test-run.log 2>&1

- name: 'Print failure logs'
if: ${{ failure() }}
Expand Down
12 changes: 12 additions & 0 deletions pkg/internal/testhelpers/containers.go
Expand Up @@ -59,6 +59,7 @@ const (
timescale2Bit = 1 << iota
multinodeBit = 1 << iota
postgres12Bit = 1 << iota
timescaleOSSBit = 1 << iota
timescaleNightlyBit = 1 << iota
)

Expand All @@ -70,6 +71,7 @@ const (
Timescale2AndPromscale ExtensionState = timescaleBit | timescale2Bit | promscaleBit
Multinode ExtensionState = timescaleBit | timescale2Bit | multinodeBit
MultinodeAndPromscale ExtensionState = timescaleBit | timescale2Bit | multinodeBit | promscaleBit
TimescaleOSS ExtensionState = timescaleBit | timescale2Bit | timescaleOSSBit

TimescaleNightly ExtensionState = timescaleBit | timescale2Bit | timescaleNightlyBit
TimescaleNightlyMultinode ExtensionState = timescaleBit | timescale2Bit | multinodeBit | timescaleNightlyBit
Expand Down Expand Up @@ -103,6 +105,10 @@ func (e *ExtensionState) UsePG12() {
*e |= postgres12Bit
}

func (e *ExtensionState) UseTimescaleDBOSS() {
*e |= timescaleBit | timescale2Bit | timescaleOSSBit
}

func (e ExtensionState) UsesTimescaleDB() bool {
return (e & timescaleBit) != 0
}
Expand All @@ -127,6 +133,10 @@ func (e ExtensionState) UsesPG12() bool {
return (e & postgres12Bit) != 0
}

func (e ExtensionState) UsesTimescaleDBOSS() bool {
return (e & timescaleOSSBit) != 0
}

var (
PromHost = "localhost"
PromPort nat.Port = "9090/tcp"
Expand Down Expand Up @@ -322,6 +332,8 @@ func StartPGContainer(
image = LatestDBWithPromscaleImageBase + ":latest-ts2-" + PGTag
case VanillaPostgres:
image = "postgres:" + PGMajor
case TimescaleOSS:
image = "timescale/timescaledb:latest-" + PGTag + "-oss"
case TimescaleNightly, TimescaleNightlyMultinode:
image = "timescaledev/timescaledb:nightly-" + PGTag
}
Expand Down
12 changes: 6 additions & 6 deletions pkg/migrations/migration_files_generated.go

Large diffs are not rendered by default.

35 changes: 33 additions & 2 deletions pkg/migrations/sql/idempotent/base.sql
Expand Up @@ -27,13 +27,35 @@ LANGUAGE SQL STABLE PARALLEL SAFE;
GRANT EXECUTE ON FUNCTION SCHEMA_CATALOG.get_default_retention_period() TO prom_reader;

CREATE OR REPLACE FUNCTION SCHEMA_CATALOG.is_timescaledb_installed()
RETURNS BOOLEAN
RETURNS BOOLEAN
AS $func$
SELECT count(*) > 0 FROM pg_extension WHERE extname='timescaledb';
$func$
LANGUAGE SQL STABLE;
GRANT EXECUTE ON FUNCTION SCHEMA_CATALOG.is_timescaledb_installed() TO prom_reader;

CREATE OR REPLACE FUNCTION SCHEMA_CATALOG.is_timescaledb_oss()
RETURNS BOOLEAN AS
$$
BEGIN
IF SCHEMA_CATALOG.is_timescaledb_installed() THEN
IF SCHEMA_CATALOG.get_timescale_major_version() >= 2 THEN
-- TimescaleDB 2.x
RETURN (SELECT current_setting('timescaledb.license') = 'apache');
ELSE
-- TimescaleDB 1.x
-- Note: We cannot use current_setting() in 1.x, otherwise we get permission errors as
-- we need to be superuser. We should not enforce the use of superuser. Hence, we take
-- help of a view.
RETURN (SELECT edition = 'apache' FROM timescaledb_information.license);
END IF;
END IF;
RETURN false;
END;
$$
LANGUAGE plpgsql;
GRANT EXECUTE ON FUNCTION SCHEMA_CATALOG.is_timescaledb_oss() TO prom_reader;

CREATE OR REPLACE FUNCTION SCHEMA_CATALOG.is_multinode()
RETURNS BOOLEAN
AS $func$
Expand Down Expand Up @@ -1340,6 +1362,10 @@ RETURNS void
AS $func$
DECLARE
BEGIN
IF SCHEMA_CATALOG.is_timescaledb_oss() THEN
RAISE NOTICE 'Compression not available in TimescaleDB-OSS. Cannot set compression on "%" metric table name', metric_table_name;
RETURN;
END IF;
IF compression_setting THEN
EXECUTE format($$
ALTER TABLE SCHEMA_DATA.%I SET (
Expand Down Expand Up @@ -1810,18 +1836,23 @@ BEGIN
IF log_verbose THEN
RAISE LOG 'promscale maintenance: data retention: starting';
END IF;

PERFORM set_config('application_name', format('promscale maintenance: data retention'), false);
CALL SCHEMA_CATALOG.execute_data_retention_policy(log_verbose=>log_verbose);
IF SCHEMA_CATALOG.get_timescale_major_version() >= 2 THEN

IF NOT SCHEMA_CATALOG.is_timescaledb_oss() AND SCHEMA_CATALOG.get_timescale_major_version() >= 2 THEN
IF log_verbose THEN
RAISE LOG 'promscale maintenance: compression: starting';
END IF;

PERFORM set_config('application_name', format('promscale maintenance: compression'), false);
CALL SCHEMA_CATALOG.execute_compression_policy(log_verbose=>log_verbose);
END IF;

IF log_verbose THEN
RAISE LOG 'promscale maintenance: finished in %', clock_timestamp()-startT;
END IF;

IF clock_timestamp()-startT > INTERVAL '12 hours' THEN
RAISE WARNING 'promscale maintenance jobs are taking too long (one run took %)', clock_timestamp()-startT
USING HINT = 'Please consider increasing the number of maintenance jobs using config_maintenance_jobs()';
Expand Down
1 change: 0 additions & 1 deletion pkg/migrations/sql/preinstall/000-utils.sql
Expand Up @@ -12,7 +12,6 @@
GRANT ALL ON TABLE SCHEMA_CATALOG.remote_commands to CURRENT_USER;
GRANT ALL ON SEQUENCE SCHEMA_CATALOG.remote_commands_seq_seq to CURRENT_USER;


CREATE OR REPLACE PROCEDURE SCHEMA_CATALOG.execute_everywhere(command_key text, command TEXT, transactional BOOLEAN = true)
AS $func$
BEGIN
Expand Down
31 changes: 30 additions & 1 deletion pkg/migrations/sql/preinstall/005-install_uda.sql
Expand Up @@ -13,11 +13,40 @@ BEGIN
END
$$ LANGUAGE PLPGSQL;

CREATE OR REPLACE FUNCTION SCHEMA_CATALOG.is_timescaledb_installed()
RETURNS BOOLEAN
AS $func$
SELECT count(*) > 0 FROM pg_extension WHERE extname='timescaledb';
$func$
LANGUAGE SQL STABLE;
GRANT EXECUTE ON FUNCTION SCHEMA_CATALOG.is_timescaledb_installed() TO prom_reader;

CREATE OR REPLACE FUNCTION SCHEMA_CATALOG.is_timescaledb_oss()
RETURNS BOOLEAN AS
$$
BEGIN
IF SCHEMA_CATALOG.is_timescaledb_installed() THEN
IF SCHEMA_CATALOG.get_timescale_major_version() >= 2 THEN
-- TimescaleDB 2.x
RETURN (SELECT current_setting('timescaledb.license') = 'apache');
ELSE
-- TimescaleDB 1.x
-- Note: We cannot use current_setting() in 1.x, otherwise we get permission errors as
-- we need to be superuser. We should not enforce the use of superuser. Hence, we take
-- help of a view.
RETURN (SELECT edition = 'apache' FROM timescaledb_information.license);
END IF;
END IF;
RETURN false;
END;
$$
LANGUAGE plpgsql;
GRANT EXECUTE ON FUNCTION SCHEMA_CATALOG.is_timescaledb_oss() TO prom_reader;

--add 2 jobs executing every 30 min by default for timescaledb 2.0
DO $$
BEGIN
IF SCHEMA_CATALOG.get_timescale_major_version() >= 2 THEN
IF NOT SCHEMA_CATALOG.is_timescaledb_oss() AND SCHEMA_CATALOG.get_timescale_major_version() >= 2 THEN
PERFORM add_job('SCHEMA_CATALOG.execute_maintenance_job', '30 min');
PERFORM add_job('SCHEMA_CATALOG.execute_maintenance_job', '30 min');
END IF;
Expand Down
29 changes: 29 additions & 0 deletions pkg/runner/client.go
Expand Up @@ -133,6 +133,15 @@ func CreateClient(cfg *Config, promMetrics *api.Metrics) (*pgclient.Client, erro
}
}

isLicenseOSS, err := isTimescaleDBOSS(conn)
if err != nil {
return nil, fmt.Errorf("fetching license information: %w", err)
}
if isLicenseOSS {
log.Warn("msg", "WARNING: Using the Apache2 version of TimescaleDB. This version does not include "+
"compression and thus performance and disk usage will be significantly negatively effected.")
}

// Election must be done after migration and version-checking: if we're on
// the wrong version we should not participate in leader-election.
elector, err = initElector(cfg, promMetrics)
Expand Down Expand Up @@ -177,6 +186,26 @@ func CreateClient(cfg *Config, promMetrics *api.Metrics) (*pgclient.Client, erro
return client, nil
}

func isTimescaleDBOSS(conn *pgx.Conn) (bool, error) {
var (
isTimescaleDB bool
isLicenseOSS bool
)
err := conn.QueryRow(context.Background(), "SELECT "+schema.Catalog+".is_timescaledb_installed()").Scan(&isTimescaleDB)
if err != nil {
return false, fmt.Errorf("error fetching whether TimescaleDB is installed: %w", err)
}
if !isTimescaleDB {
// Return false so that we don't warn for OSS TimescaleDB.
return false, nil
}
err = conn.QueryRow(context.Background(), "SELECT "+schema.Catalog+".is_timescaledb_oss()").Scan(&isLicenseOSS)
if err != nil {
return false, fmt.Errorf("error fetching TimescaleDB license: %w", err)
}
return isLicenseOSS, nil
}

// isBGWLessThanDBs checks if the background workers count is less than the database count. It should be
// called only if TimescaleDB is installed.
func isBGWLessThanDBs(conn *pgx.Conn) (bool, error) {
Expand Down
27 changes: 27 additions & 0 deletions pkg/tests/end_to_end_tests/create_test.go
Expand Up @@ -507,6 +507,9 @@ func TestInsertCompressedDuplicates(t *testing.T) {
if !*useTimescaleDB {
t.Skip("compression meaningless without TimescaleDB")
}
if *useTimescaleOSS {
t.Skip("compression not available in TimescaleDB-OSS")
}
withDB(t, *testDatabase, func(dbOwner *pgxpool.Pool, t testing.TB) {
db := testhelpers.PgxPoolWithRole(t, *testDatabase, "prom_writer")
defer db.Close()
Expand Down Expand Up @@ -625,6 +628,9 @@ func TestMetricBatcherLabelsBatching(t *testing.T) {
if !*useTimescaleDB {
t.Skip("compression meaningless without TimescaleDB")
}
if *useTimescaleOSS {
t.Skip("compression not applicable in TimescaleDB-OSS")
}
withDB(t, *testDatabase, func(dbOwner *pgxpool.Pool, t testing.TB) {
db := testhelpers.PgxPoolWithRole(t, *testDatabase, "prom_writer")
defer db.Close()
Expand Down Expand Up @@ -695,6 +701,9 @@ func TestInsertCompressed(t *testing.T) {
if !*useTimescaleDB {
t.Skip("compression meaningless without TimescaleDB")
}
if *useTimescaleOSS {
t.Skip("compression not available in TimescaleDB-OSS")
}
withDB(t, *testDatabase, func(dbOwner *pgxpool.Pool, t testing.TB) {
db := testhelpers.PgxPoolWithRole(t, *testDatabase, "prom_writer")
defer db.Close()
Expand Down Expand Up @@ -788,6 +797,9 @@ func TestInsertMultinodeAddNodes(t *testing.T) {
if !*useTimescaleDB {
t.Skip("compression meaningless without TimescaleDB")
}
if *useTimescaleOSS {
t.Skip("compression not applicable in TimescaleDB-OSS")
}
if !*useMultinode {
t.Skip("Only applies for multinode")
}
Expand Down Expand Up @@ -883,6 +895,9 @@ func TestCompressionSetting(t *testing.T) {
if !*useTimescaleDB {
t.Skip("compression meaningless without TimescaleDB")
}
if *useTimescaleOSS {
t.Skip("compression not available in TimescaleDB-OSS")
}
withDB(t, *testDatabase, func(dbOwner *pgxpool.Pool, t testing.TB) {
db := testhelpers.PgxPoolWithRole(t, *testDatabase, "prom_admin")
defer db.Close()
Expand Down Expand Up @@ -1029,6 +1044,9 @@ func TestCustomCompressionJob(t *testing.T) {
if !*useTimescale2 {
t.Skip("test meaningless without Timescale 2")
}
if *useTimescaleOSS {
t.Skip("compression not applicable in TimescaleDB-OSS")
}
withDB(t, *testDatabase, func(db *pgxpool.Pool, t testing.TB) {
dbJob := testhelpers.PgxPoolWithRole(t, *testDatabase, "prom_maintenance")
defer dbJob.Close()
Expand Down Expand Up @@ -1228,6 +1246,9 @@ func TestExecuteMaintenanceCompressionJob(t *testing.T) {
if !*useTimescale2 {
t.Skip("test meaningless without Timescale 2")
}
if *useTimescaleOSS {
t.Skip("compression not applicable in TimescaleDB-OSS")
}
withDB(t, *testDatabase, func(db *pgxpool.Pool, t testing.TB) {
dbJob := testhelpers.PgxPoolWithRole(t, *testDatabase, "prom_maintenance")
defer dbJob.Close()
Expand Down Expand Up @@ -1393,6 +1414,9 @@ func TestExecuteCompressionMetricsLocked(t *testing.T) {
if !*useTimescale2 {
t.Skip("test meaningless without Timescale 2")
}
if *useTimescaleOSS {
t.Skip("compression not applicable in TimescaleDB-OSS")
}
withDB(t, *testDatabase, func(db *pgxpool.Pool, t testing.TB) {
dbJob := testhelpers.PgxPoolWithRole(t, *testDatabase, "prom_maintenance")
defer dbJob.Close()
Expand Down Expand Up @@ -1524,6 +1548,9 @@ func TestConfigMaintenanceJobs(t *testing.T) {
if !*useTimescale2 {
t.Skip("test meaningless without Timescale 2")
}
if *useTimescaleOSS {
t.Skip("add_job() is not available in TimescaleDB OSS, hence this test is not applicable")
}
withDB(t, *testDatabase, func(dbOwner *pgxpool.Pool, t testing.TB) {
db := testhelpers.PgxPoolWithRole(t, *testDatabase, "prom_admin")
defer db.Close()
Expand Down
3 changes: 3 additions & 0 deletions pkg/tests/end_to_end_tests/delete_test.go
Expand Up @@ -149,6 +149,9 @@ func TestDeleteWithCompressedChunks(t *testing.T) {
if !*useTimescaleDB {
t.Skip("skipping delete tests with compression: compression tests cannot run if timescaledb is not installed.")
}
if *useTimescaleOSS {
t.Skip("compression not available in TimescaleDB-OSS")
}
matchers := []deleteStr{
// Normal matchers.
{
Expand Down
2 changes: 1 addition & 1 deletion pkg/tests/end_to_end_tests/functions_test.go
Expand Up @@ -385,7 +385,7 @@ func TestExtensionGapfillDelta(t *testing.T) {
var res string
err = db.QueryRow(context.Background(),
"SELECT prom_delta('2000-01-02 15:00:00 UTC'::TIMESTAMPTZ, '2000-01-02 15:45:00 UTC'::TIMESTAMPTZ, 20 * 60 * 1000, 20 * 60 * 1000, NULL, v order by t)::TEXT FROM gfd_test_table;").Scan(&res)
if err.Error() != "ERROR: time is null (SQLSTATE XX000)" {
if !(err.Error() == "ERROR: time is null (SQLSTATE XX000)" || err.Error() == `ERROR: NULL value for non-nullable argument "time" (SQLSTATE XX000)`) {
t.Error(err)
}
err = db.QueryRow(context.Background(),
Expand Down
10 changes: 10 additions & 0 deletions pkg/tests/end_to_end_tests/golden_files_test.go
Expand Up @@ -19,9 +19,13 @@ import (
var outputDifferWithoutTimescale = map[string]bool{"info_view": true}
var outputDifferWithMultinode = map[string]bool{"views": true, "info_view": true}
var outputDifferWithExtension = map[string]bool{"support": true}
var outputDifferWithTimescaleOSS = map[string]bool{"support": true}

var requiresTimescaleDB = map[string]bool{"views": true, "info_view": true, "support": true}
var requiresSingleNode = map[string]bool{"support": true}

var ignoreWhenTimescaleOSS = map[string]bool{"info_view": true, "views": true}

func TestSQLGoldenFiles(t *testing.T) {
if testing.Short() {
t.Skip("skipping integration test")
Expand All @@ -45,6 +49,9 @@ func TestSQLGoldenFiles(t *testing.T) {
if *useMultinode && requiresSingleNode[base] {
return
}
if *useTimescaleOSS && ignoreWhenTimescaleOSS[base] {
return
}

i, err := pgContainer.Exec(context.Background(), []string{"bash", "-c", "psql -U postgres -d " + *testDatabase + " -f /testdata/sql/" + base + ".sql &> /testdata/out/" + base + ".out"})
if err != nil {
Expand Down Expand Up @@ -95,6 +102,9 @@ func TestSQLGoldenFiles(t *testing.T) {
if outputDifferWithExtension[base] && !*useExtension {
expectedFile = filepath.Join("../testdata/expected/", base+mod+"-noextension.out")
}
if outputDifferWithTimescaleOSS[base] && *useTimescaleOSS {
expectedFile = filepath.Join("../testdata/expected/", base+"-timescaledb-oss.out")
}

if *updateGoldenFiles {
err = copyFile(actualFile, expectedFile)
Expand Down
3 changes: 3 additions & 0 deletions pkg/tests/end_to_end_tests/insert_compressed_chunks_test.go
Expand Up @@ -17,6 +17,9 @@ import (
)

func TestInsertInCompressedChunks(t *testing.T) {
if *useTimescaleOSS {
t.Skip("compression not applicable in TimescaleDB-OSS")
}
ts := generateSmallTimeseries()
if !*useTimescaleDB {
// Ingest in plain postgres to ensure everything works well even if TimescaleDB is not installed.
Expand Down

0 comments on commit 04ddd3f

Please sign in to comment.