diff --git a/packages/cli/bin/deals_nearby.dart b/packages/cli/bin/deals_nearby.dart index 86456131..0b759087 100644 --- a/packages/cli/bin/deals_nearby.dart +++ b/packages/cli/bin/deals_nearby.dart @@ -15,8 +15,9 @@ Future cliMain(FileSystem fs, ArgResults argResults) async { final systemsCache = SystemsCache.load(fs)!; final marketListings = await MarketListingSnapshot.load(db); - final jumpGates = JumpGateCache.load(fs); + final jumpGates = await JumpGateSnapshot.load(db); final constructionSnapshot = await ConstructionSnapshot.load(db); + // Can't use loadSystemConnectivity because need constructionSnapshot later. final systemConnectivity = SystemConnectivity.fromJumpGates(jumpGates, constructionSnapshot); final routePlanner = RoutePlanner.fromSystemsCache( diff --git a/packages/cli/bin/find_mounts.dart b/packages/cli/bin/find_mounts.dart index ec510457..fe7bc27a 100644 --- a/packages/cli/bin/find_mounts.dart +++ b/packages/cli/bin/find_mounts.dart @@ -7,10 +7,7 @@ Future command(FileSystem fs, ArgResults argResults) async { final db = await defaultDatabase(); final marketPrices = await MarketPrices.load(db); final systemsCache = SystemsCache.load(fs)!; - final jumpGateCache = JumpGateCache.load(fs); - final constructionSnapshot = await ConstructionSnapshot.load(db); - final systemConnectivity = - SystemConnectivity.fromJumpGates(jumpGateCache, constructionSnapshot); + final systemConnectivity = await loadSystemConnectivity(db); final routePlanner = RoutePlanner.fromSystemsCache( systemsCache, systemConnectivity, diff --git a/packages/cli/bin/fleet_closest_to.dart b/packages/cli/bin/fleet_closest_to.dart index 0d8db972..ca96adc4 100644 --- a/packages/cli/bin/fleet_closest_to.dart +++ b/packages/cli/bin/fleet_closest_to.dart @@ -12,10 +12,7 @@ Future command(FileSystem fs, ArgResults argResults) async { final systemsCache = SystemsCache.load(fs)!; final marketListings = await MarketListingSnapshot.load(db); - final jumpGateCache = JumpGateCache.load(fs); - final constructionSnapshot = await ConstructionSnapshot.load(db); - final systemConnectivity = - SystemConnectivity.fromJumpGates(jumpGateCache, constructionSnapshot); + final systemConnectivity = await loadSystemConnectivity(db); final routePlanner = RoutePlanner.fromSystemsCache( systemsCache, systemConnectivity, diff --git a/packages/cli/bin/idle_queue.dart b/packages/cli/bin/idle_queue.dart index 955b82b5..02fdb4c9 100644 --- a/packages/cli/bin/idle_queue.dart +++ b/packages/cli/bin/idle_queue.dart @@ -16,7 +16,7 @@ Future command(FileSystem fs, ArgResults argResults) async { if (count++ % printEvery == 0) { logger.info('$queue'); } - await queue.runOne(api, caches); + await queue.runOne(db, api, caches); } // required or main() will hang diff --git a/packages/cli/bin/jumpgate.dart b/packages/cli/bin/jumpgate.dart index dff2a5e8..b27c8a0a 100644 --- a/packages/cli/bin/jumpgate.dart +++ b/packages/cli/bin/jumpgate.dart @@ -18,8 +18,7 @@ Future command(FileSystem fs, ArgResults argResults) async { .symbol; final constructionSnapshot = await ConstructionSnapshot.load(db); - final jumpGateCache = JumpGateCache.load(fs); - final jumpGate = await jumpGateCache.getOrFetch(api, jumpGateSymbol); + final jumpGate = await getOrFetchJumpGate(db, api, jumpGateSymbol); String statusString(WaypointSymbol jumpGateSymbol) { final isUnderConstruction = diff --git a/packages/cli/bin/jumpgate_construction.dart b/packages/cli/bin/jumpgate_construction.dart index 81400955..f9ec91f8 100644 --- a/packages/cli/bin/jumpgate_construction.dart +++ b/packages/cli/bin/jumpgate_construction.dart @@ -9,10 +9,11 @@ Future command(FileSystem fs, ArgResults argResults) async { final systemsCache = SystemsCache.load(fs)!; + // Can't use loadSystemConnectivity because need constructionSnapshot later. final constructionSnapshot = await ConstructionSnapshot.load(db); - final jumpGateCache = JumpGateCache.load(fs); + final jumpGateSnapshot = await JumpGateSnapshot.load(db); final systemConnectivity = - SystemConnectivity.fromJumpGates(jumpGateCache, constructionSnapshot); + SystemConnectivity.fromJumpGates(jumpGateSnapshot, constructionSnapshot); // Find all reachable jumpgates that are under construction. final systemSymbols = diff --git a/packages/cli/bin/jumpgates_to_scan.dart b/packages/cli/bin/jumpgates_to_scan.dart index df4fba24..14344003 100644 --- a/packages/cli/bin/jumpgates_to_scan.dart +++ b/packages/cli/bin/jumpgates_to_scan.dart @@ -8,7 +8,7 @@ Future command(FileSystem fs, ArgResults argResults) async { final db = await defaultDatabase(); final systemSymbol = await myHqSystemSymbol(db); final systemsCache = SystemsCache.load(fs)!; - final jumpGateCache = JumpGateCache.load(fs); + final jumpGateSnapshot = await JumpGateSnapshot.load(db); final constructionSnapshot = await ConstructionSnapshot.load(db); final chartingSnapshot = await ChartingSnapshot.load(db); @@ -22,7 +22,7 @@ Future command(FileSystem fs, ArgResults argResults) async { while (systems.isNotEmpty || jumpGates.isNotEmpty) { if (jumpGates.isNotEmpty) { final from = jumpGates.take(); - final fromRecord = jumpGateCache.recordForSymbol(from.value); + final fromRecord = jumpGateSnapshot.recordForSymbol(from.value); if (fromRecord == null) { final chartingRecord = chartingSnapshot.getRecord(from.value); if (chartingRecord == null) { @@ -32,7 +32,7 @@ Future command(FileSystem fs, ArgResults argResults) async { } continue; } - if (!canJumpFrom(jumpGateCache, constructionSnapshot, from.value)) { + if (!canJumpFrom(jumpGateSnapshot, constructionSnapshot, from.value)) { continue; } for (final to in fromRecord.connections) { diff --git a/packages/cli/bin/market_feeder.dart b/packages/cli/bin/market_feeder.dart index a0246880..d55f65df 100644 --- a/packages/cli/bin/market_feeder.dart +++ b/packages/cli/bin/market_feeder.dart @@ -12,10 +12,7 @@ Future command(FileSystem fs, ArgResults argResults) async { final marketListings = await MarketListingSnapshot.load(db); final marketPrices = await MarketPrices.load(db); - final jumpGateCache = JumpGateCache.load(fs); - final constructionSnapshot = await ConstructionSnapshot.load(db); - final systemConnectivity = - SystemConnectivity.fromJumpGates(jumpGateCache, constructionSnapshot); + final systemConnectivity = await loadSystemConnectivity(db); final routePlanner = RoutePlanner.fromSystemsCache( systemsCache, systemConnectivity, diff --git a/packages/cli/bin/market_nearby_buys.dart b/packages/cli/bin/market_nearby_buys.dart index 41e8190e..a0c0c366 100644 --- a/packages/cli/bin/market_nearby_buys.dart +++ b/packages/cli/bin/market_nearby_buys.dart @@ -7,10 +7,7 @@ Future command(FileSystem fs, ArgResults argResults) async { final db = await defaultDatabase(); final marketPrices = await MarketPrices.load(db); final systemsCache = SystemsCache.load(fs)!; - final jumpGateCache = JumpGateCache.load(fs); - final constructionSnapshot = await ConstructionSnapshot.load(db); - final systemConnectivity = - SystemConnectivity.fromJumpGates(jumpGateCache, constructionSnapshot); + final systemConnectivity = await loadSystemConnectivity(db); final routePlanner = RoutePlanner.fromSystemsCache( systemsCache, systemConnectivity, diff --git a/packages/cli/bin/market_nearby_sells.dart b/packages/cli/bin/market_nearby_sells.dart index 6c437626..c14d02d2 100644 --- a/packages/cli/bin/market_nearby_sells.dart +++ b/packages/cli/bin/market_nearby_sells.dart @@ -7,10 +7,7 @@ Future command(FileSystem fs, ArgResults argResults) async { final db = await defaultDatabase(); final marketPrices = await MarketPrices.load(db); final systemsCache = SystemsCache.load(fs)!; - final jumpGateCache = JumpGateCache.load(fs); - final constructionSnapshot = await ConstructionSnapshot.load(db); - final systemConnectivity = - SystemConnectivity.fromJumpGates(jumpGateCache, constructionSnapshot); + final systemConnectivity = await loadSystemConnectivity(db); final routePlanner = RoutePlanner.fromSystemsCache( systemsCache, systemConnectivity, diff --git a/packages/cli/bin/routing_plan.dart b/packages/cli/bin/routing_plan.dart index b95077a2..39876cad 100644 --- a/packages/cli/bin/routing_plan.dart +++ b/packages/cli/bin/routing_plan.dart @@ -74,10 +74,7 @@ Future command(FileSystem fs, ArgResults argResults) async { throw UnimplementedError(); } - final jumpGateCache = JumpGateCache.load(fs); - final constructionSnapshot = await ConstructionSnapshot.load(db); - final systemConnectivity = - SystemConnectivity.fromJumpGates(jumpGateCache, constructionSnapshot); + final systemConnectivity = await loadSystemConnectivity(db); final routePlanner = RoutePlanner.fromSystemsCache( systemsCache, systemConnectivity, diff --git a/packages/cli/bin/simulate.dart b/packages/cli/bin/simulate.dart index 40f796a9..23463579 100644 --- a/packages/cli/bin/simulate.dart +++ b/packages/cli/bin/simulate.dart @@ -152,10 +152,7 @@ Future command(FileSystem fs, ArgResults argResults) async { final db = await defaultDatabase(); final marketPrices = await MarketPrices.load(db); final systemsCache = SystemsCache.load(fs)!; - final jumpGateCache = JumpGateCache.load(fs); - final constructionSnapshot = await ConstructionSnapshot.load(db); - final systemConnectivity = - SystemConnectivity.fromJumpGates(jumpGateCache, constructionSnapshot); + final systemConnectivity = await loadSystemConnectivity(db); final routePlanner = RoutePlanner.fromSystemsCache( systemsCache, systemConnectivity, diff --git a/packages/cli/bin/static_cache_find_missing.dart b/packages/cli/bin/static_cache_find_missing.dart index f3c540e2..91014941 100644 --- a/packages/cli/bin/static_cache_find_missing.dart +++ b/packages/cli/bin/static_cache_find_missing.dart @@ -8,10 +8,7 @@ Future command(FileSystem fs, ArgResults argResults) async { final db = await defaultDatabase(); final marketPrices = await MarketPrices.load(db); final systemsCache = SystemsCache.load(fs)!; - final jumpGateCache = JumpGateCache.load(fs); - final constructionSnapshot = await ConstructionSnapshot.load(db); - final systemConnectivity = - SystemConnectivity.fromJumpGates(jumpGateCache, constructionSnapshot); + final systemConnectivity = await loadSystemConnectivity(db); final routePlanner = RoutePlanner.fromSystemsCache( systemsCache, systemConnectivity, diff --git a/packages/cli/bin/system_routing.dart b/packages/cli/bin/system_routing.dart index ea7e6200..00ccf20b 100644 --- a/packages/cli/bin/system_routing.dart +++ b/packages/cli/bin/system_routing.dart @@ -15,10 +15,7 @@ Future command(FileSystem fs, ArgResults argResults) async { final hqSystemSymbol = await myHqSystemSymbol(db); final marketListings = await MarketListingSnapshot.load(db); final shipyardListings = ShipyardListingCache.load(fs); - final jumpGateCache = JumpGateCache.load(fs); - final constructionSnapshot = await ConstructionSnapshot.load(db); - final systemConnectivity = - SystemConnectivity.fromJumpGates(jumpGateCache, constructionSnapshot); + final systemConnectivity = await loadSystemConnectivity(db); final routePlanner = RoutePlanner.fromSystemsCache( systems, systemConnectivity, diff --git a/packages/cli/bin/system_stats.dart b/packages/cli/bin/system_stats.dart index 0e7483d7..5e930d2e 100644 --- a/packages/cli/bin/system_stats.dart +++ b/packages/cli/bin/system_stats.dart @@ -8,10 +8,11 @@ Future command(FileSystem fs, ArgResults argResults) async { logger.info('Starting from $startSystemSymbol, known reachable:'); final systemsCache = SystemsCache.load(fs)!; - final jumpGateCache = JumpGateCache.load(fs); + // Can't use loadSystemConnectivity because need jumpGateSnapshot later. + final jumpGateSnapshot = await JumpGateSnapshot.load(db); final constructionSnapshot = await ConstructionSnapshot.load(db); final systemConnectivity = - SystemConnectivity.fromJumpGates(jumpGateCache, constructionSnapshot); + SystemConnectivity.fromJumpGates(jumpGateSnapshot, constructionSnapshot); final reachableSystems = systemConnectivity.systemsReachableFrom(startSystemSymbol).toSet(); @@ -92,7 +93,7 @@ Future command(FileSystem fs, ArgResults argResults) async { // How many are cached? var cachedJumpGates = 0; - for (final record in jumpGateCache.values) { + for (final record in jumpGateSnapshot.values) { // We could sort first by system to save ourselves some lookups. final systemSymbol = record.waypointSymbol.system; if (reachableSystems.contains(systemSymbol)) { diff --git a/packages/cli/bin/system_to_chart_next.dart b/packages/cli/bin/system_to_chart_next.dart index 28eba88a..5b431c27 100644 --- a/packages/cli/bin/system_to_chart_next.dart +++ b/packages/cli/bin/system_to_chart_next.dart @@ -17,10 +17,7 @@ Future command(FileSystem fs, ArgResults argResults) async { construction, staticCaches.waypointTraits, ); - final jumpGateCache = JumpGateCache.load(fs); - final constructionSnapshot = await ConstructionSnapshot.load(db); - final systemConnectivity = - SystemConnectivity.fromJumpGates(jumpGateCache, constructionSnapshot); + final systemConnectivity = await loadSystemConnectivity(db); final shipCache = ShipCache.load(fs)!; final behaviorCache = BehaviorCache.load(fs); diff --git a/packages/cli/bin/systems_explored.dart b/packages/cli/bin/systems_explored.dart index 13f453e2..d297d548 100644 --- a/packages/cli/bin/systems_explored.dart +++ b/packages/cli/bin/systems_explored.dart @@ -82,10 +82,7 @@ Future command(FileSystem fs, ArgResults argResults) async { 'with market prices.', ); - final jumpGateCache = JumpGateCache.load(fs); - final constructionSnapshot = await ConstructionSnapshot.load(db); - final systemConnectivity = - SystemConnectivity.fromJumpGates(jumpGateCache, constructionSnapshot); + final systemConnectivity = await loadSystemConnectivity(db); final hqSystemSymbol = await myHqSystemSymbol(db); final reachableSystems = systemConnectivity.systemsReachableFrom(hqSystemSymbol); diff --git a/packages/cli/bin/systems_interesting.dart b/packages/cli/bin/systems_interesting.dart index a6798efa..3bd6b4e4 100644 --- a/packages/cli/bin/systems_interesting.dart +++ b/packages/cli/bin/systems_interesting.dart @@ -20,9 +20,9 @@ Future command(FileSystem fs, ArgResults argResults) async { final systemsCache = SystemsCache.load(fs)!; final constructionSnapshot = await ConstructionSnapshot.load(db); - final jumpGateCache = JumpGateCache.load(fs); + final jumpGateSnapshot = await JumpGateSnapshot.load(db); final systemConnectivity = - SystemConnectivity.fromJumpGates(jumpGateCache, constructionSnapshot); + SystemConnectivity.fromJumpGates(jumpGateSnapshot, constructionSnapshot); final hqSystemSymbol = await myHqSystemSymbol(db); final reachableSystems = systemConnectivity.systemsReachableFrom(hqSystemSymbol).toSet(); @@ -41,7 +41,7 @@ Future command(FileSystem fs, ArgResults argResults) async { } logger.info('of ${interestingSystemSymbols.length} interesting systems.'); - final reachableJumpGates = jumpGateCache.values.where( + final reachableJumpGates = jumpGateSnapshot.values.where( (record) => reachableSystems.contains(record.waypointSymbol.system), ); // These are not necessarily reachable (the jump gate on either side might diff --git a/packages/cli/bin/systems_nearby.dart b/packages/cli/bin/systems_nearby.dart index 5c56757b..415ccf2b 100644 --- a/packages/cli/bin/systems_nearby.dart +++ b/packages/cli/bin/systems_nearby.dart @@ -7,10 +7,7 @@ Future command(FileSystem fs, ArgResults argResults) async { await startSystemFromArg(db, argResults.rest.firstOrNull); final marketListings = await MarketListingSnapshot.load(db); - final jumpGateCache = JumpGateCache.load(fs); - final constructionSnapshot = await ConstructionSnapshot.load(db); - final systemConnectivity = - SystemConnectivity.fromJumpGates(jumpGateCache, constructionSnapshot); + final systemConnectivity = await loadSystemConnectivity(db); final connectedSystemSymbols = systemConnectivity.directlyConnectedSystemSymbols(startSystemSymbol); diff --git a/packages/cli/bin/systems_to_chart.dart b/packages/cli/bin/systems_to_chart.dart index 78cb8148..48bbd68d 100644 --- a/packages/cli/bin/systems_to_chart.dart +++ b/packages/cli/bin/systems_to_chart.dart @@ -8,10 +8,7 @@ Future command(FileSystem fs, ArgResults argResults) async { final startSystemSymbol = await startSystemFromArg(db, argResults.rest.firstOrNull); - final jumpGateCache = JumpGateCache.load(fs); - final constructionSnapshot = await ConstructionSnapshot.load(db); - final systemConnectivity = - SystemConnectivity.fromJumpGates(jumpGateCache, constructionSnapshot); + final systemConnectivity = await loadSystemConnectivity(db); final systemsCache = SystemsCache.load(fs)!; final chartingSnapshot = await ChartingSnapshot.load(db); diff --git a/packages/cli/bin/systems_to_warp_to.dart b/packages/cli/bin/systems_to_warp_to.dart index c6dc63ca..4522c116 100644 --- a/packages/cli/bin/systems_to_warp_to.dart +++ b/packages/cli/bin/systems_to_warp_to.dart @@ -15,10 +15,10 @@ Future command(FileSystem fs, ArgResults argResults) async { final startSystemSymbol = await myHqSystemSymbol(db); final staticCaches = StaticCaches.load(fs); - final jumpGateCache = JumpGateCache.load(fs); + final jumpGateSnapshot = await JumpGateSnapshot.load(db); final constructionCache = ConstructionCache(db); final systemConnectivity = SystemConnectivity.fromJumpGates( - jumpGateCache, + jumpGateSnapshot, await constructionCache.snapshot(), ); final systemsCache = SystemsCache.load(fs)!; diff --git a/packages/cli/lib/cache/caches.dart b/packages/cli/lib/cache/caches.dart index 9277f4f1..055a3410 100644 --- a/packages/cli/lib/cache/caches.dart +++ b/packages/cli/lib/cache/caches.dart @@ -99,7 +99,7 @@ class Caches { final WaypointCache waypoints; /// The cache of jump gates. - final JumpGateCache jumpGates; + final JumpGateSnapshot jumpGates; /// The cache of markets descriptions. /// This is currently updated at the top of every loop. @@ -155,7 +155,7 @@ class Caches { await ContractCache.loadOrFetch(api, fs: fs, forceRefresh: true); final behaviors = BehaviorCache.load(fs); - final jumpGates = JumpGateCache.load(fs); + final jumpGates = await JumpGateSnapshot.load(db); final constructionSnapshot = await ConstructionSnapshot.load(db); final systemConnectivity = SystemConnectivity.fromJumpGates(jumpGates, constructionSnapshot); diff --git a/packages/cli/lib/cache/jump_gate_cache.dart b/packages/cli/lib/cache/jump_gate_cache.dart index 93a6b93f..4035dac9 100644 --- a/packages/cli/lib/cache/jump_gate_cache.dart +++ b/packages/cli/lib/cache/jump_gate_cache.dart @@ -1,58 +1,28 @@ import 'package:cli/cache/caches.dart'; -import 'package:cli/cache/json_list_store.dart'; import 'package:cli/net/queries.dart'; import 'package:collection/collection.dart'; +import 'package:db/db.dart'; import 'package:types/types.dart'; /// A cached of JumpGate connections. /// Connections are not necessarily functional, you have to check /// the ConstructionCache to see if they are under construction. -class JumpGateCache extends JsonListStore { +class JumpGateSnapshot { /// Creates a new JumpGate cache. - JumpGateCache( - super.records, { - required super.fs, - super.path = defaultCacheFilePath, - }); + JumpGateSnapshot(this.values); /// Load the JumpGate values from the cache. - factory JumpGateCache.load( - FileSystem fs, { - String path = defaultCacheFilePath, - }) { - final records = JsonListStore.loadRecords( - fs, - path, - JumpGate.fromJson, - ) ?? - []; - return JumpGateCache(records, fs: fs, path: path); + static Future load(Database db) async { + final gates = await db.allJumpGates(); + return JumpGateSnapshot(gates.toList()); } - /// The default path to the cache file. - static const String defaultCacheFilePath = 'data/jump_gates.json'; - /// The JumpGate values. - List get values => records; + final List values; /// The number of waypoints in the cache. int get waypointCount => values.length; - /// Updates a [JumpGate] in the cache. - void updateJumpGate(JumpGate jumpGate) { - final index = records.indexWhere( - (record) => record.waypointSymbol == jumpGate.waypointSymbol, - ); - - if (index >= 0) { - records[index] = jumpGate; - } else { - records.add(jumpGate); - } - - save(); - } - /// Gets all jump gates for the given system. Iterable recordsForSystem(SystemSymbol systemSymbol) { return values @@ -68,19 +38,20 @@ class JumpGateCache extends JsonListStore { values.firstWhereOrNull( (record) => record.waypointSymbol == waypointSymbol, ); +} - /// Gets the JumpGate for the given waypoint symbol. - Future getOrFetch( - Api api, - WaypointSymbol waypointSymbol, { - DateTime Function() getNow = defaultGetNow, - }) async { - final cached = recordForSymbol(waypointSymbol); - if (cached != null) { - return cached; - } - final jumpGate = await getJumpGate(api, waypointSymbol); - updateJumpGate(jumpGate); - return jumpGate; +/// Gets the JumpGate for the given waypoint symbol. +Future getOrFetchJumpGate( + Database db, + Api api, + WaypointSymbol waypointSymbol, { + DateTime Function() getNow = defaultGetNow, +}) async { + final cached = await db.getJumpGate(waypointSymbol); + if (cached != null) { + return cached; } + final jumpGate = await getJumpGate(api, waypointSymbol); + await db.upsertJumpGate(jumpGate); + return jumpGate; } diff --git a/packages/cli/lib/cache/market_prices.dart b/packages/cli/lib/cache/market_prices.dart index 25bdbc92..dfb32193 100644 --- a/packages/cli/lib/cache/market_prices.dart +++ b/packages/cli/lib/cache/market_prices.dart @@ -297,6 +297,6 @@ Future recordMarketData( logger.warn('No prices for ${market.symbol}!'); } for (final price in prices) { - db.upsertMarketPrice(price); + await db.upsertMarketPrice(price); } } diff --git a/packages/cli/lib/cli.dart b/packages/cli/lib/cli.dart index 1e21ea54..b1472b1a 100644 --- a/packages/cli/lib/cli.dart +++ b/packages/cli/lib/cli.dart @@ -112,3 +112,13 @@ Future startSystemFromArg(Database db, String? arg) async { } return SystemSymbol.fromString(arg); } + +/// Shortcut for loading system connectivity when you don't care +/// about holding onto the jump gate snapshot or construction snapshot. +Future loadSystemConnectivity(Database db) async { + final jumpGateSnapshot = await JumpGateSnapshot.load(db); + final constructionSnapshot = await ConstructionSnapshot.load(db); + final systemConnectivity = + SystemConnectivity.fromJumpGates(jumpGateSnapshot, constructionSnapshot); + return systemConnectivity; +} diff --git a/packages/cli/lib/idle_queue.dart b/packages/cli/lib/idle_queue.dart index f2628055..122a36c1 100644 --- a/packages/cli/lib/idle_queue.dart +++ b/packages/cli/lib/idle_queue.dart @@ -87,10 +87,10 @@ class IdleQueue { /// Queue jump gate connections for fetching. // TODO(eseidel): Jump gate construction completion should call this. void queueJumpGateConnections( - JumpGate JumpGate, { + JumpGate jumpGate, { required int jumpDistance, }) { - for (final connection in JumpGate.connections) { + for (final connection in jumpGate.connections) { _queueJumpGate(connection, jumpDistance: jumpDistance); } } @@ -121,7 +121,7 @@ class IdleQueue { } } - Future _processNextSystem(Api api, Caches caches) async { + Future _processNextSystem(Database db, Api api, Caches caches) async { final systemRecord = _systems.take(); final systemSymbol = systemRecord.value; final jumpDistance = systemRecord.jumpDistance; @@ -150,8 +150,9 @@ class IdleQueue { // a ship there. if (waypoint.isJumpGate) { if (await caches.waypoints.isCharted(waypointSymbol)) { - final fromRecord = - await caches.jumpGates.getOrFetch(api, waypoint.symbol); + // TODO(eseidel): This doesn't change our current JumpGateSnapshot + // so we need to be careful that this method doesn't need the latest. + final fromRecord = await getOrFetchJumpGate(db, api, waypoint.symbol); // Don't follow links where the source is under construction, but // do follow them if the destination is. This will have the effect // of loading all the starter systems into our db, even if we can't @@ -177,13 +178,13 @@ class IdleQueue { } /// Run one fetch. - Future runOne(Api api, Caches caches) async { + Future runOne(Database db, Api api, Caches caches) async { if (isDone) { return; } // Service systems before jumpgates to make a breadth-first search. if (_systems.isNotEmpty) { - await _processNextSystem(api, caches); + await _processNextSystem(db, api, caches); return; } if (_jumpGates.isNotEmpty) { diff --git a/packages/cli/lib/logic.dart b/packages/cli/lib/logic.dart index 3c5ecf61..8db133b9 100644 --- a/packages/cli/lib/logic.dart +++ b/packages/cli/lib/logic.dart @@ -24,10 +24,11 @@ Future _waitIfNeeded(ShipWaiterEntry entry) async { } Future _runIdleTasksIfPossible( - ShipWaiterEntry entry, - IdleQueue queue, + Database db, Api api, Caches caches, + IdleQueue queue, + ShipWaiterEntry entry, ) async { if (!config.serviceIdleQueue) { return; @@ -45,7 +46,7 @@ Future _runIdleTasksIfPossible( api.requestCounts, 'idle queue', queue.minProcessingTime, - () async => await queue.runOne(api, caches), + () async => await queue.runOne(db, api, caches), ); } } @@ -82,7 +83,7 @@ Future advanceShips( final shipSymbol = entry.shipSymbol; final waitUntil = entry.waitUntil; - await _runIdleTasksIfPossible(entry, queue, api, caches); + await _runIdleTasksIfPossible(db, api, caches, queue, entry); await _waitIfNeeded(entry); final ship = caches.ships[shipSymbol]; if (shipFilter != null && !shipFilter(ship)) { diff --git a/packages/cli/lib/nav/system_connectivity.dart b/packages/cli/lib/nav/system_connectivity.dart index 011ce473..d2be408a 100644 --- a/packages/cli/lib/nav/system_connectivity.dart +++ b/packages/cli/lib/nav/system_connectivity.dart @@ -96,11 +96,11 @@ class _Clusters { /// Returns true if it's possible to jump from the provided jumpgate. /// it's important to also check if it's possible to jump to the destination. bool canJumpFrom( - JumpGateCache jumpGateCache, + JumpGateSnapshot jumpGates, ConstructionSnapshot constructionSnapshot, WaypointSymbol from, ) { - final record = jumpGateCache.recordForSymbol(from); + final record = jumpGates.recordForSymbol(from); // If we don't know about the fromGate, we can't jump. if (record == null) { return false; @@ -129,12 +129,12 @@ bool canJumpTo( /// Returns true if we know it's possible to jump between the two waypoints. bool canJumpBetween( - JumpGateCache jumpGateCache, + JumpGateSnapshot jumpGates, ConstructionSnapshot constructionSnapshot, { required WaypointSymbol from, required WaypointSymbol to, }) { - return canJumpFrom(jumpGateCache, constructionSnapshot, from) && + return canJumpFrom(jumpGates, constructionSnapshot, from) && canJumpTo(constructionSnapshot, to); } @@ -154,18 +154,18 @@ class _Connections { } _Connections.fromSnapshots( - JumpGateCache jumpGateCache, + JumpGateSnapshot jumpGates, ConstructionSnapshot constructionSnapshot, ) { - // JumpGateCache caches responses from the server. We may not yet have + // JumpGateSnapshot caches responses from the server. We may not yet have // cached both sides of a jump gate, so this fills in the gaps. - for (final record in jumpGateCache.values) { - final from = record.waypointSymbol; - if (!canJumpFrom(jumpGateCache, constructionSnapshot, from)) { + for (final jumpGate in jumpGates.values) { + final from = jumpGate.waypointSymbol; + if (!canJumpFrom(jumpGates, constructionSnapshot, from)) { continue; } final fromSystem = from.system; - for (final to in record.connections) { + for (final to in jumpGate.connections) { if (!canJumpTo(constructionSnapshot, to)) { continue; } @@ -197,7 +197,7 @@ class SystemConnectivity { /// Creates a new SystemConnectivity from the systemsCache. factory SystemConnectivity.fromJumpGates( - JumpGateCache jumpGates, + JumpGateSnapshot jumpGates, ConstructionSnapshot constructionSnapshot, ) { final connections = @@ -213,7 +213,7 @@ class SystemConnectivity { /// Updates the SystemConnectivity from the given caches. void updateFromJumpGates( - JumpGateCache jumpGates, + JumpGateSnapshot jumpGates, ConstructionSnapshot constructionSnapshot, ) { _connections = _Connections.fromSnapshots(jumpGates, constructionSnapshot); diff --git a/packages/cli/test/cache/caches_mock.dart b/packages/cli/test/cache/caches_mock.dart index 5881d702..4ee75fff 100644 --- a/packages/cli/test/cache/caches_mock.dart +++ b/packages/cli/test/cache/caches_mock.dart @@ -11,7 +11,7 @@ class _MockConstructionCache extends Mock implements ConstructionCache {} class _MockContractCache extends Mock implements ContractCache {} -class _MockJumpGateCache extends Mock implements JumpGateCache {} +class _MockJumpGateSnapshot extends Mock implements JumpGateSnapshot {} class _MockMarketCache extends Mock implements MarketCache {} @@ -86,7 +86,7 @@ Caches mockCaches() { static: staticCaches, construction: _MockConstructionCache(), systemConnectivity: _MockSystemConnectivity(), - jumpGates: _MockJumpGateCache(), + jumpGates: _MockJumpGateSnapshot(), shipyardListings: _MockShipyardListingCache(), ); } diff --git a/packages/cli/test/cache/caches_test.dart b/packages/cli/test/cache/caches_test.dart index bc584c2f..45f44c95 100644 --- a/packages/cli/test/cache/caches_test.dart +++ b/packages/cli/test/cache/caches_test.dart @@ -74,6 +74,7 @@ void main() { when(db.allMarketPrices).thenAnswer((_) async => []); when(db.allShipyardListings).thenAnswer((_) async => []); when(db.allShipyardPrices).thenAnswer((_) async => []); + when(db.allJumpGates).thenAnswer((_) async => []); final fs = MemoryFileSystem.test(); fs.file(SystemsCache.defaultCacheFilePath).createSync(recursive: true); diff --git a/packages/cli/test/nav/system_connectivity_test.dart b/packages/cli/test/nav/system_connectivity_test.dart index dca60259..2e151b09 100644 --- a/packages/cli/test/nav/system_connectivity_test.dart +++ b/packages/cli/test/nav/system_connectivity_test.dart @@ -1,7 +1,6 @@ import 'package:cli/cache/construction_cache.dart'; import 'package:cli/cache/jump_gate_cache.dart'; import 'package:cli/nav/system_connectivity.dart'; -import 'package:file/memory.dart'; import 'package:mocktail/mocktail.dart'; import 'package:test/test.dart'; import 'package:types/types.dart'; @@ -10,20 +9,18 @@ class _MockConstructionSnapshot extends Mock implements ConstructionSnapshot {} void main() { test('SystemConnectivity.fromJumpGates', () async { - final fs = MemoryFileSystem.test(); final a = WaypointSymbol.fromString('X-A-A'); final b = WaypointSymbol.fromString('X-B-B'); final constructionSnapshot = _MockConstructionSnapshot(); when(() => constructionSnapshot.isUnderConstruction(a)).thenReturn(false); - final jumpGateCache = JumpGateCache( + final jumpGates = JumpGateSnapshot( [ JumpGate(waypointSymbol: a, connections: {b}), ], - fs: fs, ); final unknownB = SystemConnectivity.fromJumpGates( - jumpGateCache, + jumpGates, constructionSnapshot, ); // If construction status of 'b' is not known, then there is no path. @@ -34,7 +31,7 @@ void main() { when(() => constructionSnapshot.isUnderConstruction(b)).thenReturn(false); final knownB = SystemConnectivity.fromJumpGates( - jumpGateCache, + jumpGates, constructionSnapshot, ); expect( diff --git a/packages/db/lib/db.dart b/packages/db/lib/db.dart index 385ce2fb..11550e2c 100644 --- a/packages/db/lib/db.dart +++ b/packages/db/lib/db.dart @@ -4,6 +4,7 @@ import 'package:db/src/chart.dart'; import 'package:db/src/construction.dart'; import 'package:db/src/extraction.dart'; import 'package:db/src/faction.dart'; +import 'package:db/src/jump_gate.dart'; import 'package:db/src/market_listing.dart'; import 'package:db/src/market_price.dart'; import 'package:db/src/query.dart'; @@ -365,4 +366,20 @@ class Database { Future upsertShipyardPrice(ShipyardPrice price) async { await insertOne(upsertShipyardPriceQuery(price)); } + + /// Get all jump gates from the database. + Future> allJumpGates() async { + return queryMany(allJumpGatesQuery(), jumpGateFromColumnMap); + } + + /// Add a jump gate to the database. + Future upsertJumpGate(JumpGate jumpGate) async { + await insertOne(upsertJumpGateQuery(jumpGate)); + } + + /// Get the jump gate for the given waypoint symbol. + Future getJumpGate(WaypointSymbol waypointSymbol) async { + final query = getJumpGateQuery(waypointSymbol); + return queryOne(query, jumpGateFromColumnMap); + } } diff --git a/packages/db/lib/src/jump_gate.dart b/packages/db/lib/src/jump_gate.dart new file mode 100644 index 00000000..bc964063 --- /dev/null +++ b/packages/db/lib/src/jump_gate.dart @@ -0,0 +1,40 @@ +import 'package:db/src/query.dart'; +import 'package:types/types.dart'; + +/// Query all jump gates. +Query allJumpGatesQuery() => const Query( + 'SELECT * FROM jump_gate_', + parameters: {}, + ); + +/// Upsert a jump gate. +Query upsertJumpGateQuery(JumpGate jumpGate) => Query( + ''' + INSERT INTO jump_gate_ ( + waypoint_symbol, + connections, + ) VALUES ( + @waypoint_symbol, + @connections, + ) + ON CONFLICT (waypoint_symbol) DO UPDATE SET + connections = @connections, + ''', + parameters: jumpGateToColumnMap(jumpGate), + ); + +/// Get a jump gate by symbol. +Query getJumpGateQuery(WaypointSymbol waypointSymbol) => Query( + 'SELECT * FROM jump_gate_ WHERE waypoint_symbol = @waypoint_symbol', + parameters: {'waypoint_symbol': waypointSymbol.toJson()}, + ); + +/// Convert a jump gate to a column map. +Map jumpGateToColumnMap(JumpGate jumpGate) { + return jumpGate.toJson(); +} + +/// Convert a result row to a jump gate. +JumpGate jumpGateFromColumnMap(Map values) { + return JumpGate.fromJson(values); +} diff --git a/packages/db/sql/flows/drop_tables.sql b/packages/db/sql/flows/drop_tables.sql index abb0ce37..12ba4edb 100644 --- a/packages/db/sql/flows/drop_tables.sql +++ b/packages/db/sql/flows/drop_tables.sql @@ -12,3 +12,4 @@ DROP TABLE IF EXISTS "market_listing_" CASCADE; DROP TABLE IF EXISTS "shipyard_listing_" CASCADE; DROP TABLE IF EXISTS "shipyard_price_" CASCADE; DROP TABLE IF EXISTS "market_price_" CASCADE; +DROP TABLE IF EXISTS "jump_gate_" CASCADE; diff --git a/packages/db/sql/tables/15_jump_gate.sql b/packages/db/sql/tables/15_jump_gate.sql new file mode 100644 index 00000000..5c1bea99 --- /dev/null +++ b/packages/db/sql/tables/15_jump_gate.sql @@ -0,0 +1,7 @@ +-- Describes a jump gate. +CREATE TABLE IF NOT EXISTS "jump_gate_" ( + -- The symbol of the jump gate. + "symbol" text NOT NULL PRIMARY KEY, + -- Other jump gates this connects to. + "connections" text [] NOT NULL, +); \ No newline at end of file