Skip to content

Add solution for Challenge 30 by imankhodadi#1074

Closed
imankhodadi wants to merge 1 commit intoRezaSi:mainfrom
imankhodadi:challenge-30-imankhodadi-1767709981
Closed

Add solution for Challenge 30 by imankhodadi#1074
imankhodadi wants to merge 1 commit intoRezaSi:mainfrom
imankhodadi:challenge-30-imankhodadi-1767709981

Conversation

@imankhodadi
Copy link
Contributor

Challenge 30 Solution

Submitted by: @imankhodadi
Challenge: Challenge 30

Description

This PR contains my solution for Challenge 30.

Changes

  • Added solution file to challenge-30/submissions/imankhodadi/solution-template.go

Testing

  • Solution passes all test cases
  • Code follows Go best practices

Thank you for reviewing my submission! 🚀

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 6, 2026

Walkthrough

A new Go file introduces a context management utility with a ContextManager interface and simpleContextManager implementation, providing methods for creating cancellable/timeout contexts, value propagation, task execution with cleanup, waiting/progress tracking, work simulation, concurrent item processing, operation chaining, and rate-limited execution.

Changes

Cohort / File(s) Summary
Context Management Utility
challenge-30/submissions/imankhodadi/solution-template.go
New file introducing ContextManager interface with 12 methods (CreateCancellableContext, CreateTimeoutContext, AddValue, GetValue, ExecuteWithContext, ExecuteWithContextTimeout, WaitForCompletion, WaitWithProgress, CreateContextWithMultipleValues, ExecuteWithCleanup, ChainOperations, RateLimitedExecution). Includes simpleContextManager concrete implementation, factory constructor NewContextManager(), and top-level helper functions (ProcessItems, ProcessItemsConcurrently, SimulateWork, SimulateWorkWithProgress). Supports concurrent processing with worker pools, cancellation propagation, cleanup callbacks, and rate limiting. Includes demonstrative main routine.

Estimated Code Review Effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly Related PRs

Pre-merge checks

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 42.86% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The PR title directly matches the main objective—adding a solution for Challenge 30 by the specified author.
Description check ✅ Passed The PR description is clearly related to the changeset, explaining that it contains a Challenge 30 solution and specifying the file location.

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.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Fix all issues with AI Agents
In @challenge-30/submissions/imankhodadi/solution-template.go:
- Around line 45-51: GetValue currently treats ctx.Value(key)==nil the same as
"not found", which misreports keys intentionally set to nil; modify the context
storage to wrap values in a sentinel/wrapper type so nil can be distinguished
(e.g., introduce a private wrapper type like contextEntry and change the setter
function (SetValue/wherever values are stored) to store &contextEntry{v:
originalValue} and change simpleContextManager.GetValue to look up
ctx.Value(key), type-assert to *contextEntry and return entry.v with true when
present, otherwise return nil,false; update any callers that write to context to
use the new wrapper.
- Around line 246-263: The results slice is preallocated to len(items) so if
workers exit early due to context cancellation you return a slice with empty
strings; also the error-handling branch checking result.err is dead because
workers never send non-nil errors. Fix by either (A) making workers send real
errors into resultChan (set result.err on failure) so the existing err-handling
path can be reached, or (B) remove the unreachable result.err check and instead
build/return a compact slice of only successfully processed values by appending
to a local slice when receiving from resultChan and return that slice along with
ctx.Err(); update code around resultChan, results, and cancel() accordingly
(refer to resultChan, results, cancel(), and the worker send site that currently
sends nil).
- Around line 227-238: ProcessItems currently returns items without applying the
same transformation as ProcessItemsConcurrently (which uses strings.ToUpper on
work.item); make their behavior consistent by applying the same transformation
in ProcessItems — either call the same helper used in ProcessItemsConcurrently
or apply strings.ToUpper when building the processed string (e.g., use
fmt.Sprintf("processed_%s", strings.ToUpper(item)) or extract a processItem(item
string) function and use it from both ProcessItems and ProcessItemsConcurrently
so both produce identical output).
🧹 Nitpick comments (4)
challenge-30/submissions/imankhodadi/solution-template.go (4)

28-31: Comment is inconsistent with implementation.

The comment suggests returning ContextManager interface type, but the function returns *simpleContextManager. While returning a concrete type is idiomatic Go ("accept interfaces, return structs"), consider either updating the comment to reflect the current approach or changing the return type if interface abstraction is desired.


53-59: Unused function getStringValue.

This helper function is defined but never called anywhere in the file. Consider removing it or adding a usage if it's intended for future use.


126-138: Unused description parameter.

The description parameter is assigned a default value but never used. Either remove it or use it (e.g., for logging or error messages).

🔎 If removing the parameter
-func SimulateWork(ctx context.Context, workDuration time.Duration, description string) error {
-	if description == "" {
-		description = "work"
-	}
+func SimulateWork(ctx context.Context, workDuration time.Duration) error {
 	timer := time.NewTimer(workDuration)
 	defer timer.Stop()

Note: This would require updating the call site in ProcessItems as well.


282-295: Operations cannot perform cooperative cancellation.

The operations functions don't receive ctx, so they cannot check for cancellation during execution. Cancellation is only checked between operations. If an operation blocks for a long time, the chain won't respond to cancellation until it completes.

Consider whether the signature should be operations []func(context.Context) error for cooperative cancellation within operations.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 438db3f and 959b248.

📒 Files selected for processing (1)
  • challenge-30/submissions/imankhodadi/solution-template.go
🔇 Additional comments (9)
challenge-30/submissions/imankhodadi/solution-template.go (9)

1-9: LGTM!

Package declaration and imports are appropriate. All imported packages (context, fmt, strings, sync, time) are standard library and used throughout the implementation.


11-24: LGTM!

The ContextManager interface is well-designed with a comprehensive set of context-handling methods. The method signatures follow Go conventions and provide good coverage for common context operations.


65-76: Goroutine leak when context is cancelled.

When ctx.Done() fires, ExecuteWithContext returns immediately but the spawned goroutine continues until task() completes. This is documented in the comments, which is good, but callers should be aware:

  1. The leaked goroutine will eventually complete and write to resultChan, which is fine since it's buffered.
  2. Long-running or blocking tasks will hold resources until they complete.

Also, task doesn't receive ctx, so it cannot cooperatively check for cancellation. Consider whether the signature should be task func(context.Context) error to allow cooperative cancellation.


85-123: LGTM!

Both waiting methods are well-implemented:

  • Proper use of defer timer.Stop() and defer ticker.Stop() to prevent resource leaks.
  • Good handling of edge cases with minimum interval of 1ms.
  • Correct deadline checking in WaitWithProgress.

165-188: LGTM!

Good implementation of sequential item processing with proper cancellation checks before each item. Returning partial results on cancellation is a useful pattern that allows callers to use completed work.


265-272: LGTM!

The implementation correctly chains context.WithValue calls. While map iteration order is non-deterministic in Go, this doesn't affect correctness since context value lookup is key-based.


274-280: LGTM!

Proper use of defer ensures cleanup runs regardless of task outcome. The nil check for cleanup is a good defensive practice.


297-315: LGTM!

Good implementation of interval-based rate limiting. The ticker ensures tasks start at fixed intervals (not delays from completion). Proper cleanup with defer ticker.Stop() and context-aware execution.


316-333: LGTM!

Good demonstration of basic usage. The defer cancel() ensures proper cleanup of the context.

Comment on lines +45 to +51
func (cm *simpleContextManager) GetValue(ctx context.Context, key interface{}) (interface{}, bool) {
value := ctx.Value(key)
if value == nil {
return nil, false
}
return value, true
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

GetValue cannot distinguish between "key not found" and "key exists with nil value".

ctx.Value(key) returns nil for both missing keys and keys with nil values. If a caller intentionally stores nil, GetValue will incorrectly report the key as absent.

Consider whether this edge case matters for your use case. If it does, you could use a wrapper type or sentinel value.

🤖 Prompt for AI Agents
In @challenge-30/submissions/imankhodadi/solution-template.go around lines 45 -
51, GetValue currently treats ctx.Value(key)==nil the same as "not found", which
misreports keys intentionally set to nil; modify the context storage to wrap
values in a sentinel/wrapper type so nil can be distinguished (e.g., introduce a
private wrapper type like contextEntry and change the setter function
(SetValue/wherever values are stored) to store &contextEntry{v: originalValue}
and change simpleContextManager.GetValue to look up ctx.Value(key), type-assert
to *contextEntry and return entry.v with true when present, otherwise return
nil,false; update any callers that write to context to use the new wrapper.

Comment on lines +227 to +238
for work := range itemChan {
select {
case <-ctx.Done():
// Don't process this item, just return
return
default:
// Process item
processed := fmt.Sprintf("processed_%s", strings.ToUpper(work.item))
resultChan <- result{work.index, processed, nil}
}
}
}()
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Inconsistent processing behavior with ProcessItems.

ProcessItemsConcurrently applies strings.ToUpper to items (line 234), but ProcessItems does not. This inconsistency could surprise callers expecting the same transformation logic.

-				processed := fmt.Sprintf("processed_%s", strings.ToUpper(work.item))
+				processed := fmt.Sprintf("processed_%s", work.item)
📝 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
for work := range itemChan {
select {
case <-ctx.Done():
// Don't process this item, just return
return
default:
// Process item
processed := fmt.Sprintf("processed_%s", strings.ToUpper(work.item))
resultChan <- result{work.index, processed, nil}
}
}
}()
for work := range itemChan {
select {
case <-ctx.Done():
// Don't process this item, just return
return
default:
// Process item
processed := fmt.Sprintf("processed_%s", work.item)
resultChan <- result{work.index, processed, nil}
}
}
}()
🤖 Prompt for AI Agents
In @challenge-30/submissions/imankhodadi/solution-template.go around lines 227 -
238, ProcessItems currently returns items without applying the same
transformation as ProcessItemsConcurrently (which uses strings.ToUpper on
work.item); make their behavior consistent by applying the same transformation
in ProcessItems — either call the same helper used in ProcessItemsConcurrently
or apply strings.ToUpper when building the processed string (e.g., use
fmt.Sprintf("processed_%s", strings.ToUpper(item)) or extract a processItem(item
string) function and use it from both ProcessItems and ProcessItemsConcurrently
so both produce identical output).

Comment on lines +246 to +263
results := make([]string, len(items))
for result := range resultChan {
if result.err != nil {
cancel() // Signal other workers to stop
// Drain remaining results
for range resultChan {
}
return nil, result.err
}
results[result.index] = result.value
}

// Check if context was cancelled
if ctx.Err() != nil {
return results, ctx.Err()
}
return results, nil
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Results may contain empty strings for unprocessed items.

When context is cancelled, workers exit early and some items may not be processed. The results slice is pre-allocated with len(items), so unprocessed indices remain as empty strings. The function returns this partially-filled slice with ctx.Err().

Additionally, the error handling block (lines 248-253) is unreachable because workers never set result.err to a non-nil value (line 235 always passes nil).

Consider either:

  1. Documenting this behavior (partial results with empty strings on cancellation)
  2. Returning only successfully processed items
  3. Removing the dead error-handling code
🤖 Prompt for AI Agents
In @challenge-30/submissions/imankhodadi/solution-template.go around lines 246 -
263, The results slice is preallocated to len(items) so if workers exit early
due to context cancellation you return a slice with empty strings; also the
error-handling branch checking result.err is dead because workers never send
non-nil errors. Fix by either (A) making workers send real errors into
resultChan (set result.err on failure) so the existing err-handling path can be
reached, or (B) remove the unreachable result.err check and instead build/return
a compact slice of only successfully processed values by appending to a local
slice when receiving from resultChan and return that slice along with ctx.Err();
update code around resultChan, results, and cancel() accordingly (refer to
resultChan, results, cancel(), and the worker send site that currently sends
nil).

@RezaSi RezaSi closed this Jan 7, 2026
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.

2 participants