Skip to content

Fix: Duplicate weather API call during startup and refresh#182

Open
bosankus wants to merge 1 commit into
developfrom
fix/duplicate-weather-api-call-at-startup-and-refresh
Open

Fix: Duplicate weather API call during startup and refresh#182
bosankus wants to merge 1 commit into
developfrom
fix/duplicate-weather-api-call-at-startup-and-refresh

Conversation

@bosankus

@bosankus bosankus commented Jun 21, 2026

Copy link
Copy Markdown
Owner

Issue

  • NA

What was changed?

  • Duplicate weather API call during startup and refresh
  • Added mutex lock for room storage get/set last updated weather data

Summary by CodeRabbit

  • Bug Fixes

    • Improved weather data refresh with explicit error handling for network failures.
    • Enhanced thread-safety for timestamp tracking operations.
    • Air quality data now properly synchronized with weather updates.
  • Refactor

    • Updated error handling mechanism to explicitly surface network connectivity issues instead of returning null values.

@bosankus bosankus self-assigned this Jun 21, 2026
@coderabbitai

coderabbitai Bot commented Jun 21, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

WeatherRepository.refreshWeatherData contract changes from WeatherForecast? to Result<WeatherForecast?>. The network implementation returns Result.failure(NetworkException) instead of null/throwing. The app-layer repository consumes this via fold. WeatherStorageImpl gains Mutex-guarded timestamp map access. SavedLocation.id adds @SerialName("_id").

Changes

Result-based error handling and storage fixes

Layer / File(s) Summary
Network repository contract and implementation
network/.../repository/WeatherRepository.kt, network/.../repository/WeatherRepositoryImpl.kt
WeatherRepository interface updates refreshWeatherData to return Result<WeatherForecast?> with failure KDoc. WeatherRepositoryImpl adds NetworkException import, replaces null-return-on-offline with Result.failure(NetworkException(NETWORK_UNAVAILABLE, ...)), and replaces thrown wrapped exception with Result.failure(e).
App repository consuming Result with fold
app/.../data/repository/WeatherRepositoryImpl.kt
Replaces the prior nullable-check with Result.fold: onSuccess extracts airQuality from it.data?.airQuality, saves weather and air-quality entities, and updates the timestamp; onFailure provides an explicit but empty branch.
Storage Mutex synchronization and SerialName annotation
storage/.../impl/WeatherStorageImpl.kt, network/.../model/LocationModels.kt
WeatherStorageImpl adds timestampsMutex: Mutex and wraps all locationTimestamps reads, writes, and clears in withLock. SavedLocation.id gains @SerialName("_id") for MongoDB-compatible serialization.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐇 Hop hop, no more null to dread,
Results now wrap the future ahead.
The mutex guards the timestamp nest,
And _id is annotated best.
A fold of success, a fold of fail,
This bunny's code shall never bail! 🌤️

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 20.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Fix: Duplicate weather API call during startup and refresh' directly addresses the main issue being resolved: preventing duplicate API calls. However, the actual changes span multiple files addressing result handling, serialization, and mutex synchronization—all necessary to fix this issue. The title accurately captures the high-level problem being solved, though it doesn't reflect the comprehensive nature of the solution.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/duplicate-weather-api-call-at-startup-and-refresh

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@app/src/main/java/bose/ankush/weatherify/data/repository/WeatherRepositoryImpl.kt`:
- Around line 65-67: The onFailure block in the WeatherRepositoryImpl class is
empty and silently discards errors without any logging or propagation. Replace
the empty onFailure implementation with proper error handling by logging the
exception using an appropriate logging mechanism (such as Log.e or a logger
instance), and include the error message and stack trace for debugging. If the
method signature supports it, consider also propagating the error to the UI
layer through a callback, LiveData, Flow, or similar mechanism so users are
informed of failures.

In
`@network/src/commonMain/kotlin/bose/ankush/network/repository/WeatherRepositoryImpl.kt`:
- Around line 34-36: The catch block in WeatherRepositoryImpl.kt that catches
broad Exception type is inadvertently catching CancellationException, which
should propagate to maintain structured concurrency. Modify the catch block to
check if the caught exception is a CancellationException and explicitly rethrow
it before wrapping other exceptions in Result.failure, following the defensive
pattern used in other parts of the codebase like TokenManager.kt and
PaymentViewModel.kt.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b289cbf5-fb4e-4238-89c3-6d1d13476500

📥 Commits

Reviewing files that changed from the base of the PR and between 26c17f9 and 59179a5.

📒 Files selected for processing (5)
  • app/src/main/java/bose/ankush/weatherify/data/repository/WeatherRepositoryImpl.kt
  • network/src/commonMain/kotlin/bose/ankush/network/model/LocationModels.kt
  • network/src/commonMain/kotlin/bose/ankush/network/repository/WeatherRepository.kt
  • network/src/commonMain/kotlin/bose/ankush/network/repository/WeatherRepositoryImpl.kt
  • storage/src/androidMain/kotlin/bose/ankush/storage/impl/WeatherStorageImpl.kt

Comment on lines +65 to +67
onFailure = {
// Log error or pass it to UI
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Empty onFailure silently swallows errors.

The failure branch discards the exception without logging or propagating it. This means:

  • No observability into network failures
  • Users won't know why a refresh produced no change
  • Debugging production issues becomes harder

At minimum, log the error. Consider also propagating to the UI if the method signature allows.

🔧 Proposed fix to add logging
                     onFailure = {
-                        // Log error or pass it to UI
+                        // TODO: Consider propagating to UI for user feedback
+                        Log.e("WeatherRepository", "Failed to refresh weather data", it)
                     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
onFailure = {
// Log error or pass it to UI
}
onFailure = {
// TODO: Consider propagating to UI for user feedback
Log.e("WeatherRepository", "Failed to refresh weather data", it)
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@app/src/main/java/bose/ankush/weatherify/data/repository/WeatherRepositoryImpl.kt`
around lines 65 - 67, The onFailure block in the WeatherRepositoryImpl class is
empty and silently discards errors without any logging or propagation. Replace
the empty onFailure implementation with proper error handling by logging the
exception using an appropriate logging mechanism (such as Log.e or a logger
instance), and include the error message and stack trace for debugging. If the
method signature supports it, consider also propagating the error to the UI
layer through a callback, LiveData, Flow, or similar mechanism so users are
informed of failures.

Comment on lines 34 to +36
} catch (e: Exception) {
throw Exception("Network | Failed to refresh weather data: ${e.message}", e)
// retryWithExponentialBackoff already normalizes failures to NetworkException.
Result.failure(e)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Check what exceptions retryWithExponentialBackoff throws and whether it handles CancellationException

# Find the implementation of retryWithExponentialBackoff
ast-grep --pattern $'suspend fun retryWithExponentialBackoff($$$) {
  $$$
}'

# Also search for any CancellationException handling
rg -n -C5 'CancellationException' --type=kotlin

Repository: bosankus/Compose-Weatherify

Length of output: 25115


🏁 Script executed:

# Find retryWithExponentialBackoff function definition
rg -n "retryWithExponentialBackoff" --type=kotlin -B2 -A10

Repository: bosankus/Compose-Weatherify

Length of output: 10782


🏁 Script executed:

# View the full WeatherRepositoryImpl.kt file to see lines 16-37
cat -n network/src/commonMain/kotlin/bose/ankush/network/repository/WeatherRepositoryImpl.kt

Repository: bosankus/Compose-Weatherify

Length of output: 1693


🏁 Script executed:

# View the complete NetworkUtils.kt file
cat -n network/src/commonMain/kotlin/bose/ankush/network/utils/NetworkUtils.kt

Repository: bosankus/Compose-Weatherify

Length of output: 1552


Catching CancellationException breaks structured concurrency.

The broad catch (e: Exception) will also catch CancellationException, which should propagate to allow proper coroutine cancellation. Although retryWithExponentialBackoff currently converts CancellationException to NetworkException, the defensive pattern of explicitly propagating CancellationException should be applied here to match the rest of the codebase (e.g., TokenManager.kt, PaymentViewModel.kt).

🔧 Proposed fix
         } catch (e: Exception) {
+            if (e is kotlinx.coroutines.CancellationException) throw e
             // retryWithExponentialBackoff already normalizes failures to NetworkException.
             Result.failure(e)
         }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
} catch (e: Exception) {
throw Exception("Network | Failed to refresh weather data: ${e.message}", e)
// retryWithExponentialBackoff already normalizes failures to NetworkException.
Result.failure(e)
} catch (e: Exception) {
if (e is kotlinx.coroutines.CancellationException) throw e
// retryWithExponentialBackoff already normalizes failures to NetworkException.
Result.failure(e)
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@network/src/commonMain/kotlin/bose/ankush/network/repository/WeatherRepositoryImpl.kt`
around lines 34 - 36, The catch block in WeatherRepositoryImpl.kt that catches
broad Exception type is inadvertently catching CancellationException, which
should propagate to maintain structured concurrency. Modify the catch block to
check if the caught exception is a CancellationException and explicitly rethrow
it before wrapping other exceptions in Result.failure, following the defensive
pattern used in other parts of the codebase like TokenManager.kt and
PaymentViewModel.kt.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant