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

feat: introduce license manager and feature tiers #17396

Merged
merged 22 commits into from
Jun 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions .typos.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ extend-exclude = [
"src/sqlparser/tests/testdata/",
"src/frontend/planner_test/tests/testdata",
"src/tests/sqlsmith/tests/freeze",
"src/license/src/manager.rs",
"Cargo.lock",
"**/Cargo.toml",
"**/go.mod",
Expand Down
28 changes: 24 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ members = [
"src/frontend/planner_test",
"src/java_binding",
"src/jni_core",
"src/license",
"src/meta",
"src/meta/dashboard",
"src/meta/model_v2",
Expand Down Expand Up @@ -203,6 +204,7 @@ risingwave_frontend = { path = "./src/frontend" }
risingwave_hummock_sdk = { path = "./src/storage/hummock_sdk" }
risingwave_hummock_test = { path = "./src/storage/hummock_test" }
risingwave_hummock_trace = { path = "./src/storage/hummock_trace" }
risingwave_license = { path = "./src/license" }
risingwave_mem_table_spill_test = { path = "./src/stream/spill_test" }
risingwave_meta = { path = "./src/meta" }
risingwave_meta_dashboard = { path = "./src/meta/dashboard" }
Expand Down
1 change: 1 addition & 0 deletions e2e_test/batch/catalog/pg_settings.slt.part
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ postmaster backup_storage_url
postmaster barrier_interval_ms
postmaster checkpoint_frequency
postmaster enable_tracing
postmaster license_key
postmaster max_concurrent_creating_streaming_jobs
postmaster pause_on_next_bootstrap
user application_name
Expand Down
59 changes: 59 additions & 0 deletions e2e_test/error_ui/simple/license.slt
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Set the license key to a free tier key.
statement ok
ALTER SYSTEM SET license_key TO 'eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJydy10ZXN0IiwidGllciI6ImZyZWUiLCJpc3MiOiJ0ZXN0LnJpc2luZ3dhdmUuY29tIiwiZXhwIjo5OTk5OTk5OTk5fQ.ALC3Kc9LI6u0S-jeMB1YTxg1k8Azxwvc750ihuSZgjA_e1OJC9moxMvpLrHdLZDzCXHjBYi0XJ_1lowmuO_0iPEuPqN5AFpDV1ywmzJvGmMCMtw3A2wuN7hhem9OsWbwe6lzdwrefZLipyo4GZtIkg5ZdwGuHzm33zsM-X5gl_Ns4P6axHKiorNSR6nTAyA6B32YVET_FAM2YJQrXqpwA61wn1XLfarZqpdIQyJ5cgyiC33BFBlUL3lcRXLMLeYe6TjYGeV4K63qARCjM9yeOlsRbbW5ViWeGtR2Yf18pN8ysPXdbaXm_P_IVhl3jCTDJt9ctPh6pUCbkt36FZqO9A';

query error
SELECT rw_test_paid_tier();
----
db error: ERROR: Failed to run the query

Caused by these errors (recent errors listed first):
1: Expr error
2: error while evaluating expression `test_paid_tier()`
3: feature TestPaid is only available for tier Paid and above, while the current tier is Free

Hint: You may want to set a license key with `ALTER SYSTEM SET license_key = '...';` command.


# Set the license key to an invalid key.
statement ok
ALTER SYSTEM SET license_key TO 'invalid';

query error
SELECT rw_test_paid_tier();
----
db error: ERROR: Failed to run the query

Caused by these errors (recent errors listed first):
1: Expr error
2: error while evaluating expression `test_paid_tier()`
3: feature TestPaid is not available due to license error
4: invalid license key
5: InvalidToken


# Set the license key to empty. This demonstrates the default behavior in production, i.e., free tier.
statement ok
ALTER SYSTEM SET license_key TO '';

query error
SELECT rw_test_paid_tier();
----
db error: ERROR: Failed to run the query

Caused by these errors (recent errors listed first):
1: Expr error
2: error while evaluating expression `test_paid_tier()`
3: feature TestPaid is only available for tier Paid and above, while the current tier is Free

Hint: You may want to set a license key with `ALTER SYSTEM SET license_key = '...';` command.


# Set the license key to default. In debug mode, this will set the license key to a paid tier key.
statement ok
ALTER SYSTEM SET license_key TO DEFAULT;

query T
SELECT rw_test_paid_tier();
----
t
1 change: 1 addition & 0 deletions proto/expr.proto
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,7 @@ message ExprNode {
// ------------------------
// Internal functions
VNODE = 1101;
TEST_PAID_TIER = 1102;
// Non-deterministic functions
PROCTIME = 2023;
PG_SLEEP = 2024;
Expand Down
1 change: 1 addition & 0 deletions proto/meta.proto
Original file line number Diff line number Diff line change
Expand Up @@ -603,6 +603,7 @@ message SystemParams {
optional string wasm_storage_url = 14 [deprecated = true];
optional bool enable_tracing = 15;
optional bool use_new_object_prefix_strategy = 16;
optional string license_key = 17;
}

message GetSystemParamsRequest {}
Expand Down
1 change: 1 addition & 0 deletions src/common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ risingwave_common_estimate_size = { workspace = true }
risingwave_common_metrics = { path = "./metrics" }
risingwave_common_proc_macro = { workspace = true }
risingwave_error = { workspace = true }
risingwave_license = { workspace = true }
risingwave_pb = { workspace = true }
rust_decimal = { version = "1", features = ["db-postgres", "maths"] }
rw_iter_util = { workspace = true }
Expand Down
11 changes: 9 additions & 2 deletions src/common/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2278,6 +2278,13 @@ pub struct CompactionConfig {
mod tests {
use super::*;

fn default_config_for_docs() -> RwConfig {
let mut config = RwConfig::default();
// Set `license_key` to empty to avoid showing the test-only license key in the docs.
config.system.license_key = Some("".to_owned());
config
}

/// This test ensures that `config/example.toml` is up-to-date with the default values specified
/// in this file. Developer should run `./risedev generate-example-config` to update it if this
/// test fails.
Expand All @@ -2287,7 +2294,7 @@ mod tests {
# Check detailed comments in src/common/src/config.rs";

let actual = expect_test::expect_file!["../../config/example.toml"];
let default = toml::to_string(&RwConfig::default()).expect("failed to serialize");
let default = toml::to_string(&default_config_for_docs()).expect("failed to serialize");

let expected = format!("{HEADER}\n\n{default}");
actual.assert_eq(&expected);
Expand Down Expand Up @@ -2328,7 +2335,7 @@ mod tests {
.collect();

let toml_doc: BTreeMap<String, toml::Value> =
toml::from_str(&toml::to_string(&RwConfig::default()).unwrap()).unwrap();
toml::from_str(&toml::to_string(&default_config_for_docs()).unwrap()).unwrap();
toml_doc.into_iter().for_each(|(name, value)| {
set_default_values("".to_string(), name, value, &mut configs);
});
Expand Down
2 changes: 1 addition & 1 deletion src/common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,12 +75,12 @@ pub mod field_generator;
pub mod hash;
pub mod log;
pub mod memory;
pub use risingwave_common_metrics as metrics;
pub use risingwave_common_metrics::{
monitor, register_guarded_gauge_vec_with_registry,
register_guarded_histogram_vec_with_registry, register_guarded_int_counter_vec_with_registry,
register_guarded_int_gauge_vec_with_registry,
};
pub use {risingwave_common_metrics as metrics, risingwave_license as license};
pub mod lru;
pub mod opts;
pub mod range;
Expand Down
11 changes: 8 additions & 3 deletions src/common/src/system_param/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@
// See the License for the specific language governing permissions and
// limitations under the License.

use risingwave_license::LicenseManager;

use super::diff::SystemParamsDiff;
use super::reader::SystemParamsReader;
use crate::util::tracing::layer::toggle_otel_layer;

/// Node-independent handler for system parameter changes.
///
/// Currently, it is only used to enable or disable the distributed tracing layer.
#[derive(Debug)]
pub struct CommonHandler;

Expand All @@ -32,8 +32,13 @@ impl CommonHandler {

/// Handle the change of system parameters.
pub fn handle_change(&self, diff: &SystemParamsDiff) {
// Toggle the distributed tracing layer.
if let Some(enabled) = diff.enable_tracing {
toggle_otel_layer(enabled)
toggle_otel_layer(enabled);
}
// Refresh the license key.
if let Some(key) = diff.license_key.as_ref() {
LicenseManager::get().refresh(key);
BugenZhao marked this conversation as resolved.
Show resolved Hide resolved
}
}
}
1 change: 1 addition & 0 deletions src/common/src/system_param/local_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ impl LocalSystemParamsManager {
let this = Self::new_inner(initial_params.clone());

// Spawn a task to run the common handler.
// TODO(bugen): this may be spawned multiple times under standalone deployment, though idempotent.
tokio::spawn({
let mut rx = this.tx.subscribe();
async move {
Expand Down
16 changes: 15 additions & 1 deletion src/common/src/system_param/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ use std::ops::RangeBounds;
use std::str::FromStr;

use paste::paste;
use risingwave_license::TEST_PAID_LICENSE_KEY;
use risingwave_pb::meta::PbSystemParams;

use self::diff::SystemParamsDiff;
Expand Down Expand Up @@ -60,6 +61,15 @@ impl_param_value!(u64);
impl_param_value!(f64);
impl_param_value!(String => &'a str);

/// Set the default value of `license_key` to [`TEST_PAID_LICENSE_KEY`] in debug mode.
fn default_license_key() -> String {
if cfg!(debug_assertions) {
TEST_PAID_LICENSE_KEY.to_owned()
} else {
"".to_owned()
}
}

/// Define all system parameters here.
///
/// To match all these information, write the match arm as follows:
Expand Down Expand Up @@ -87,7 +97,8 @@ macro_rules! for_all_params {
{ max_concurrent_creating_streaming_jobs, u32, Some(1_u32), true, "Max number of concurrent creating streaming jobs.", },
{ pause_on_next_bootstrap, bool, Some(false), true, "Whether to pause all data sources on next bootstrap.", },
{ enable_tracing, bool, Some(false), true, "Whether to enable distributed tracing.", },
{ use_new_object_prefix_strategy, bool, None, false, "Whether to split object prefix.", },
{ use_new_object_prefix_strategy, bool, None, false, "Whether to split object prefix.", },
{ license_key, String, Some(default_license_key()), true, "The license key to activate enterprise features.", },
}
};
}
Expand Down Expand Up @@ -148,6 +159,8 @@ macro_rules! def_default {
pub mod default {
use std::sync::LazyLock;

use super::*;

for_all_params!(def_default_opt);
for_all_params!(def_default);
}
Expand Down Expand Up @@ -444,6 +457,7 @@ mod tests {
(PAUSE_ON_NEXT_BOOTSTRAP_KEY, "false"),
(ENABLE_TRACING_KEY, "true"),
(USE_NEW_OBJECT_PREFIX_STRATEGY_KEY, "false"),
(LICENSE_KEY_KEY, "foo"),
("a_deprecated_param", "foo"),
];

Expand Down
4 changes: 4 additions & 0 deletions src/common/src/system_param/reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,4 +168,8 @@ where
.enable_tracing
.unwrap_or_else(default::enable_tracing)
}

fn license_key(&self) -> &str {
self.inner().license_key.as_deref().unwrap_or_default()
}
}
1 change: 1 addition & 0 deletions src/config/docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ This page is automatically generated by `./risedev generate-example-config`
| checkpoint_frequency | There will be a checkpoint for every n barriers. | 1 |
| data_directory | Remote directory for storing data and metadata objects. | |
| enable_tracing | Whether to enable distributed tracing. | false |
| license_key | The license key to activate enterprise features. | "" |
| max_concurrent_creating_streaming_jobs | Max number of concurrent creating streaming jobs. | 1 |
| parallel_compact_size_mb | The size of parallel task for one compact/flush job. | 512 |
| pause_on_next_bootstrap | Whether to pause all data sources on next bootstrap. | false |
Expand Down
1 change: 1 addition & 0 deletions src/config/example.toml
Original file line number Diff line number Diff line change
Expand Up @@ -238,3 +238,4 @@ bloom_false_positive = 0.001
max_concurrent_creating_streaming_jobs = 1
pause_on_next_bootstrap = false
enable_tracing = false
license_key = ""
1 change: 1 addition & 0 deletions src/expr/impl/src/scalar/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ pub use to_jsonb::*;
mod encrypt;
mod external;
mod inet;
mod test_license;
mod to_timestamp;
mod translate;
mod trigonometric;
Expand Down
27 changes: 27 additions & 0 deletions src/expr/impl/src/scalar/test_license.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright 2024 RisingWave Labs
//
// 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.

use risingwave_common::license::Feature;
use risingwave_expr::{function, ExprError, Result};

/// A function that checks if the `TestPaid` feature is available.
///
/// It's mainly for testing purposes only.
#[function("test_paid_tier() -> boolean")]
pub fn test_paid_tier() -> Result<bool> {
Feature::TestPaid
.check_available()
.map_err(|e| ExprError::Internal(anyhow::Error::from(e)))?;
Ok(true)
}
1 change: 1 addition & 0 deletions src/frontend/src/binder/expr/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1426,6 +1426,7 @@ impl Binder {
("pg_is_in_recovery", raw_literal(ExprImpl::literal_bool(false))),
// internal
("rw_vnode", raw_call(ExprType::Vnode)),
("rw_test_paid_tier", raw_call(ExprType::TestPaidTier)), // for testing purposes
// TODO: choose which pg version we should return.
("version", raw_literal(ExprImpl::literal_varchar(current_cluster_version()))),
// non-deterministic
Expand Down
1 change: 1 addition & 0 deletions src/frontend/src/expr/pure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@ impl ExprVisitor for ImpureAnalyzer {
}
// expression output is not deterministic
Type::Vnode
| Type::TestPaidTier
| Type::Proctime
| Type::PgSleep
| Type::PgSleepFor
Expand Down
Loading
Loading