Last active
June 7, 2023 12:23
-
-
Save zboralski/fb5299f309748d3c5f21b86ec7318560 to your computer and use it in GitHub Desktop.
Temporal Worker GetLimiter
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"fmt" | |
"reflect" | |
"unsafe" | |
"go.temporal.io/sdk/worker" | |
"golang.org/x/time/rate" | |
) | |
// GetTaskLimiter can retrieve the taskLimiter from a worker.Worker instance. | |
// This function uses reflection to access the internal taskLimiter field | |
// of the worker.Worker instance. Please note that this function serves | |
// as a workaround to demonstrate the importance and potential usage of making | |
// taskLimiter accessible, and isn't a recommended long-term solution. | |
// | |
// https://github.com/temporalio/sdk-go/issues/1130 | |
func GetTaskLimiter(w worker.Worker) (*rate.Limiter, error) { | |
if w == nil { | |
return nil, fmt.Errorf("worker is nil") | |
} | |
// Extract the value from the interface | |
value := reflect.ValueOf(w) | |
if value.Kind() == reflect.Interface && !value.IsNil() { | |
value = value.Elem() | |
} | |
// If the value is a pointer, dereference it | |
if value.Kind() == reflect.Ptr && !value.IsNil() { | |
value = value.Elem() | |
} | |
// If the value is now a struct, attempt to get the activityWorker field | |
if value.Kind() != reflect.Struct { | |
return nil, fmt.Errorf("expected a struct, but got: %s", value.Kind()) | |
} | |
activityWorkerField := value.FieldByName("activityWorker") | |
if !(activityWorkerField.IsValid() && activityWorkerField.CanAddr()) { | |
return nil, fmt.Errorf("field 'activityWorker' is not valid or can't be addressed") | |
} | |
// Create a new Value that treats activityWorker as if it were exported | |
activityWorkerField = reflect.NewAt(activityWorkerField.Type(), unsafe.Pointer(activityWorkerField.UnsafeAddr())).Elem() | |
// Check if activityWorker is valid and then access baseWorker | |
if activityWorkerField.Kind() == reflect.Ptr && !activityWorkerField.IsNil() { | |
activityWorkerField = activityWorkerField.Elem() | |
} | |
if activityWorkerField.Kind() != reflect.Struct { | |
return nil, fmt.Errorf("expected a struct, but got: %s", activityWorkerField.Kind()) | |
} | |
baseWorkerField := activityWorkerField.FieldByName("worker") | |
if !(baseWorkerField.IsValid() && baseWorkerField.CanAddr()) { | |
return nil, fmt.Errorf("field 'worker' in 'activityWorker' is not valid or can't be addressed") | |
} | |
// Create a new Value that treats worker (baseWorker) as if it were exported | |
baseWorkerField = reflect.NewAt(baseWorkerField.Type(), unsafe.Pointer(baseWorkerField.UnsafeAddr())).Elem() | |
// Check if baseWorker is valid and then access taskLimiter | |
if baseWorkerField.Kind() == reflect.Ptr && !baseWorkerField.IsNil() { | |
baseWorkerField = baseWorkerField.Elem() | |
} | |
if baseWorkerField.Kind() != reflect.Struct { | |
return nil, fmt.Errorf("expected a struct, but got: %s", baseWorkerField.Kind()) | |
} | |
taskLimiterField := baseWorkerField.FieldByName("taskLimiter") | |
if !(taskLimiterField.IsValid() && taskLimiterField.CanAddr()) { | |
return nil, fmt.Errorf("field 'taskLimiter' in 'baseWorker' is not valid or can't be addressed") | |
} | |
// Finally return the taskLimiter as *rate.Limiter | |
return (*rate.Limiter)(unsafe.Pointer(taskLimiterField.Pointer())), nil | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment