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

Read from the audit database #5038

Merged
merged 3 commits into from
Dec 3, 2024
Merged

Read from the audit database #5038

merged 3 commits into from
Dec 3, 2024

Conversation

nickgerace
Copy link
Contributor

@nickgerace nickgerace commented Nov 27, 2024

Description

This PR ensures that we read from the audit database for the audit logs interface rather than directly from the NATS JetStream stream. This is a drop-in replacement that does not result in a change to the front end. The user experience, however, should be vastly improved with one caveat that we'll cover at the end.

To accomplish this, we always read from the database in SDF and in integration tests, but enabling the audit logs app for forklift will still be opt-in for production use cases. However, for CI integration tests, local integration tests and development builds with buck2 and cargo, forklift will have the audit logs app enabled by default.

This commit removes the ability to read from the stream in the dal wholesale and also uses the new "AuditLogRow" struct and its methods to read from the database. We rely on the compound index for the "audit_logs" table in the audit database for quick querying.

Context

This switchover was implemented for a variety of reasons, including but not limited to the following:

  • Data correctness in the frontend (e.g. the number of rows you ask for should now be what you get, or at least however many exist for your currently selected change set)
  • Performance
  • Rich query semantics
  • Data segregation by database

Test Related Refactoring

Ever wondered why our services often have a "from_config" method that calls a "from_services" method? It's because we don't want services bootstrapping their own duplicate inner services if we don't need to in tests. Now, forklift is able to take in an active audit database context that's shared with the test author's audit database context. Well, the inner PgPool is shared anyway.

Known Issue

If you manipulate filters in the audit logs UI, specifically clicking "Clear Filters", you will notice a significant slowdown. This is not specific to this PR and is an issue in "app/web" that will be solved in a follow-up PR.

@nickgerace nickgerace changed the title Incomplete attempt at reading from audit database Read from the audit database Dec 2, 2024
@nickgerace nickgerace force-pushed the nick/3307a92 branch 4 times, most recently from 926d1c4 to b274c8b Compare December 2, 2024 23:54
@nickgerace nickgerace marked this pull request as ready for review December 2, 2024 23:56
This commit ensures that we read from the audit database for the audit
logs interface rather than directly from the NATS JetStream stream. This
is a drop-in replacement that does not result in a change to the front
end. The user experience, however, should be vastly improved with one
caveat that we'll cover at the end.

To accomplish this, we always read from the database in SDF and in
integration tests, but enabling the audit logs app for forklift will
still be opt-in for production use cases. However, for CI integration
tests, local integration tests and development builds with buck2 and
cargo, forklift will have the audit logs app enabled by default.

This commit removes the ability to read from the stream in the dal
wholesale and also uses the new "AuditLogRow" struct and its methods
to read from the database. We rely on the compound index for the
"audit_logs" table in the audit database for quick querying.

Context:

This switchover was implemented for a variety of reasons, including
but not limited to the following:

- Data correctness in the frontend (e.g. the number of rows you ask for
  should now be what you get, or at least however many exist for your
  currently selected change set)
- Performance
- Rich query semantics
- Data segregation by database

Test related refactoring:

Ever wondered why our services often have a "from_config" method that
calls a "from_services" method? It's because we don't want services
bootstrapping their own duplicate inner services if we don't need to in
tests. Now, forklift is able to take in an active audit database context
that's shared with the test author's audit database context. Well, the
inner PgPool is shared anyway.

Known issue:

If you manipulate filters in the audit logs UI, specifically clicking
"Clear Filters", you will notice a significant slowdown. This is not
specific to this PR and is an issue in "app/web" that will be solved
in a follow-up PR.

Co-authored-by: Fletcher Nichol <[email protected]>
Signed-off-by: Nick Gerace <[email protected]>
@@ -1927,6 +1927,7 @@ name = "dal-test"
version = "0.1.0"
dependencies = [
"async-recursion",
"audit-logs",
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm going to break up this crate in a future PR, starting with separating the database and stream functionalities.

Comment on lines +50 to +52
/// A row in the audit logs table of the audit database.
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct AuditLogRow {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't love this struct name, but I'm waiting to refactor this once we know it works.

Comment on lines +31 to +38
/// The default [`PgPoolConfig`] used in the [`AuditDatabaseConfig`].
pub fn default_pg_pool_config() -> PgPoolConfig {
PgPoolConfig {
dbname: DBNAME.into(),
application_name: APPLICATION_NAME.into(),
..Default::default()
}
}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Needed for TestContext assembly

const ENV_VAR_PG_USER: &str = "SI_TEST_PG_USER";
const ENV_VAR_PG_PORT: &str = "SI_TEST_PG_PORT";
const ENV_VAR_KEEP_OLD_DBS: &str = "SI_TEST_KEEP_OLD_DBS";

const ENV_VAR_LAYER_CACHE_PG_DBNAME: &str = "SI_TEST_LAYER_CACHE_PG_DBNAME";
const ENV_VAR_AUDIT_PG_DBNAME: &str = "SI_TEST_AUDIT_PG_DBNAME";
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@fnichol @johnrwatson we may need to populate this for CI

Copy link
Contributor

Choose a reason for hiding this comment

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

Nope, that all looks good, dal and sdf-server integration test ran okay!

let connection_metadata = Arc::new(nats.metadata().to_owned());
let jetstream_context = jetstream::new(nats);

let server = forklift_server::Server::from_services(
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Use from_services pattern rather than from_config

jetstream_context: jetstream::Context,
instance_id: &str,
concurrency_limit: usize,
audit_bag: Option<(AuditDatabaseContext, usize)>,
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This was a pain. Before, forklift constructed the context at the very possible last second, which was awesome for production use cases. However, if you already had a context with an in PgPool... oops. Now, we handle that.

Comment on lines +62 to +66
#[derive(Debug)]
struct Assembler {
change_set_cache: HashMap<ChangeSetId, ChangeSet>,
user_cache: HashMap<UserPk, User>,
}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This was ported from the prior implemented with the NATS JetStream stream. We may want the metadata that these caches provide for the frontend in the database in its own columns, but we decided to just extend the metadata on the way out to app/web for now.

cc @britmyerss @fnichol since we talked about this

Comment on lines +422 to +423
#test_context.nats_conn().clone(),
#test_context.audit_database_context().to_owned(),
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Just take the context already in use

@nickgerace nickgerace requested a review from fnichol December 3, 2024 00:05
@fnichol
Copy link
Contributor

fnichol commented Dec 3, 2024

/try

1 similar comment
@fnichol
Copy link
Contributor

fnichol commented Dec 3, 2024

/try

fnichol
fnichol previously approved these changes Dec 3, 2024
@fnichol
Copy link
Contributor

fnichol commented Dec 3, 2024

/try

@fnichol
Copy link
Contributor

fnichol commented Dec 3, 2024

/try

@fnichol fnichol added this pull request to the merge queue Dec 3, 2024
@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to failed status checks Dec 3, 2024
Merged via the queue into main with commit accc159 Dec 3, 2024
49 checks passed
@fnichol fnichol deleted the nick/3307a92 branch December 3, 2024 20:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants