-
Notifications
You must be signed in to change notification settings - Fork 56
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
6c4f815
commit b11892c
Showing
7 changed files
with
348 additions
and
31 deletions.
There are no files selected for viewing
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
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
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
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
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
package skip | ||
|
||
import ( | ||
"reflect" | ||
"slices" | ||
"strings" | ||
) | ||
|
||
// CanSkipExternalRequest checks if the external request can be skipped based on the plan and state. | ||
// Two of the same objects are supplied as parameters, together with the operation that is being performed. | ||
// The function uses the `skip_on` struct tag to determine if the field should be skipped. | ||
// The value of the `skip_on` tag is a comma-separated list of operations that mean that changes to this field value do not require an external request and are in state only. | ||
// The function will return true if the external request can be skipped, false otherwise. | ||
func CanSkipExternalRequest[T any](a, b T, operation string) bool { | ||
valA := reflect.ValueOf(a) | ||
valB := reflect.ValueOf(b) | ||
|
||
// Since we are using generics, we know that the types of a and b are the same. | ||
// Therefore we can check the type of a to determine if it is a struct. | ||
if valA.Kind() != reflect.Struct { | ||
return false | ||
} | ||
|
||
typeOfA := valA.Type() | ||
// iterate over all fields of the struct | ||
for i := 0; i < typeOfA.NumField(); i++ { | ||
field := typeOfA.Field(i) | ||
// Check if the field has the skip_on tag | ||
// If it doesn't we need to compare the valued as we cannot determine if the field should be skipped. | ||
// If the field has the skip_on tag, we can check if the operation is in the list of operations that should be skipped. | ||
tag := field.Tag.Get("skip_on") | ||
if tag != "" { | ||
// Split the tag values by comma and check if the operation is in the list. | ||
// If the operation is in the list, then this field represents a change in state only | ||
// and does not require an external request to be made. | ||
// Therefore we can skip tp the next field. | ||
tagValues := strings.Split(tag, ",") | ||
if slices.Contains(tagValues, operation) { | ||
continue | ||
} | ||
} | ||
|
||
// If we get here then we need to compare the field values. | ||
// By now we have determined that the struct fields do not have a valid skip value for this operation. | ||
// Therefore if the field values are not equal, then the external request cannot be skipped. | ||
fieldA := valA.Field(i) | ||
fieldB := valB.Field(i) | ||
|
||
if !fieldA.IsValid() || !fieldB.IsValid() { | ||
return false | ||
} | ||
if !reflect.DeepEqual(fieldA.Interface(), fieldB.Interface()) { | ||
return false | ||
} | ||
} | ||
return true | ||
} |
Oops, something went wrong.