-
Notifications
You must be signed in to change notification settings - Fork 35
[mobile config] track asset ownership (part 1) #1102
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
base: main
Are you sure you want to change the base?
Conversation
a3f3591 to
0a9724e
Compare
0a9724e to
397eafd
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR implements asset ownership tracking for mobile gateways by adding owner and owner_changed_at fields to the gateway system. The implementation includes database schema changes, backfill functionality for existing gateways, and updates to the tracker logic to detect and record owner changes.
Key Changes:
- Added
ownerandowner_changed_atfields to the Gateway model and database - Implemented backfill functionality to populate owner data for existing gateways with NULL owners
- Updated gateway tracker to detect owner changes and create new records when ownership changes
- Removed unused import CLI functionality
Reviewed changes
Copilot reviewed 14 out of 15 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| mobile_config/migrations/20251215132218_add_owner_hash_to_gateways.sql | Adds owner and owner_changed_at columns to gateways table |
| mobile_config/migrations/20251209173943_drop_mobile_radio_tracker.sql | Removes obsolete mobile_radio_tracker table |
| mobile_config/src/gateway/db.rs | Adds owner fields to Gateway struct and implements get_null_owners and update_owners methods |
| mobile_config/src/gateway/metadata_db.rs | Adds owner field to MobileHotspotInfo with LEFT JOIN to asset_owners table |
| mobile_config/src/gateway/tracker.rs | Implements backfill_gateway_owners function and updates execute to track owner changes |
| mobile_config/tests/integrations/gateway_tracker.rs | Adds comprehensive tests for owner tracking and backfill functionality |
| mobile_config/tests/integrations/common/gateway_db.rs | Introduces TestGatewayBuilder for simplified test gateway construction |
| mobile_config/tests/integrations/common/gateway_metadata_db.rs | Adds helper functions and table creation for asset_owners |
| mobile_config/tests/integrations/gateway_service*.rs | Updates tests to use TestGatewayBuilder and adds owner fields to manual Gateway construction |
| mobile_config/src/cli/mod.rs | Removes unused Import CLI command |
| mobile_config/src/cli/import.rs | Deleted - removes unused import functionality |
| mobile_config/Cargo.toml | Adds derive_builder as dev dependency |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if let Err(e) = backfill_gateway_owners(&self.pool, &self.metadata).await { | ||
| tracing::error!("backfill_gateway_owners is faled. {e}"); | ||
| } |
Copilot
AI
Dec 17, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The backfill function runs on every service start which could cause performance issues if there are many gateways. Consider adding a check to run this only once (e.g., using a migration flag or a separate one-time command) or adding a mechanism to prevent it from running repeatedly after the initial backfill is complete.
| let gateway1: Gateway = TestGatewayBuilder::default() | ||
| .address(address1.clone()) | ||
| .gateway_type(GatewayType::WifiIndoor) | ||
| .created_at(now) | ||
| .inserted_at(now) | ||
| .refreshed_at(now) | ||
| .last_changed_at(now_plus_10) | ||
| .elevation(2) | ||
| .azimuth(161) | ||
| .location(loc1) | ||
| .location_changed_at(now_plus_5) | ||
| .location_asserts(1) | ||
| .build()? | ||
| .into(); |
Copilot
AI
Dec 17, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The test expects antenna to be 18 (line 85), but the TestGatewayBuilder for gateway1 doesn't explicitly set the antenna field. Looking at the builder definition, the default antenna value is Some(18), so this works. However, this implicit dependency on the default value makes the test fragile. Consider explicitly setting .antenna(18) in the builder to make the test's expectations clear and prevent future breakage if the default changes.
| @@ -0,0 +1,3 @@ | |||
| ALTER TABLE gateways | |||
| ADD COLUMN IF NOT EXISTS owner VARCHAR(255), | |||
Copilot
AI
Dec 17, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The migration file name includes "hash" (add_owner_hash_to_gateways) but the migration only adds owner and owner_changed_at columns, not anything hash-related. The file name should be updated to accurately reflect what the migration does, such as "add_owner_to_gateways.sql".
| ADD COLUMN IF NOT EXISTS owner VARCHAR(255), | |
| ADD COLUMN IF NOT EXISTS owner VARCHAR(255), | |
| ADD COLUMN IF NOT EXISTS owner_hash VARCHAR(255), |
| let owner_changed = if gw.owner.is_none() { | ||
| false | ||
| } else { | ||
| gw.owner != last_gw.owner | ||
| }; |
Copilot
AI
Dec 17, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The owner change detection logic treats the case where the new owner is None as "no change" (lines 178-182). However, if a gateway previously had an owner and it changes to None, this should be detected as an owner change. Consider updating the logic to handle the case where the owner changes from Some(value) to None.
| let owner_changed = if gw.owner.is_none() { | |
| false | |
| } else { | |
| gw.owner != last_gw.owner | |
| }; | |
| let owner_changed = gw.owner != last_gw.owner; |
| sqlx::query( | ||
| r#" | ||
| CREATE TABLE asset_owners ( | ||
| asset character varying(255) NULL, | ||
| owner character varying(255) NULL, | ||
| created_at timestamptz, | ||
| updated_at timestamptz, | ||
| last_block integer | ||
| );"#, |
Copilot
AI
Dec 17, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The asset_owners test table creation doesn't include any indexes on the asset column, but the queries in insert_asset_owner and update_asset_owner filter by asset. While this is acceptable for testing with small datasets, consider adding a comment noting that the production database should have proper indexes on the asset column for performance.
mobile_config/src/gateway/tracker.rs
Outdated
| let mut interval = tokio::time::interval(self.interval); | ||
|
|
||
| if let Err(e) = backfill_gateway_owners(&self.pool, &self.metadata).await { | ||
| tracing::error!("backfill_gateway_owners is faled. {e}"); |
Copilot
AI
Dec 17, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Spelling error: "faled" should be "failed".
| tracing::error!("backfill_gateway_owners is faled. {e}"); | |
| tracing::error!("backfill_gateway_owners is failed. {e}"); |
| }, | ||
| location_asserts: self.num_location_asserts.map(|n| n as u32), | ||
| owner: self.owner.clone(), | ||
| owner_changed_at: Some(refreshed_at), |
Copilot
AI
Dec 17, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The owner_changed_at is being set in the to_gateway() conversion, but this should be set based on when the owner actually changed, not always to refreshed_at. This could lead to incorrect owner_changed_at timestamps on initial creation or when the owner hasn't actually changed.
| owner_changed_at: Some(refreshed_at), | |
| // Do not infer owner_changed_at from refreshed_at; this should be set where owner changes are tracked | |
| owner_changed_at: None, |
| // last_changed_at should also be updated since owner changed (In next owner implementing stage). | ||
| // But currently, it stays the same. After full implementation change `now` to `update_time` |
Copilot
AI
Dec 17, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comment mentions "In next owner implementing stage" which suggests incomplete implementation. However, looking at the tracker.rs code (lines 184-185), there's a TODO comment that aligns with this. The test expects last_changed_at to remain at now, but this may not reflect the final desired behavior where owner changes should also update last_changed_at. Consider updating this test expectation to match the final intended behavior or removing the comment if this is the expected behavior.
| // last_changed_at should also be updated since owner changed (In next owner implementing stage). | |
| // But currently, it stays the same. After full implementation change `now` to `update_time` | |
| // Verify that last_changed_at was not updated when the owner changed. | |
| // This test asserts the current behavior where last_changed_at remains equal to `now`. |
This is stage 1 of starting to track the
owner(withowner_changed_at) field.ownerandowner_changed_atfields were added to the gateways tablelast_changed_atis not updated at this stage, since I don't want to affect API behavior for now.P.S. The backfill function (locally) with prod db takes around 30 seconds. (second start takes nothing sine early exit works
On the second stage after we sure everything is ok in prod I'm gonna add new fields to grpc response