github.com/xmidt-org/webpa-common@v1.11.9/store/cachePeriod.go (about)

     1  package store
     2  
     3  import (
     4  	"fmt"
     5  	"strconv"
     6  	"time"
     7  )
     8  
     9  // CachePeriod is a custom type which describes the amount of time before
    10  // a cached value is considered to have been expired.  This type has
    11  // several reserved values that govern caching behavior.
    12  type CachePeriod time.Duration
    13  
    14  const (
    15  	// CachePeriodForever is a special value that means a cache never expires
    16  	CachePeriodForever CachePeriod = 0
    17  
    18  	// CachePeriodForeverValue is the string value indicating that a cache never expires
    19  	CachePeriodForeverValue string = "forever"
    20  
    21  	// CachePeriodNever is a special value indicating something must never be cached.
    22  	// Any negative value for CachePeriod will be interpreted as this value.
    23  	CachePeriodNever CachePeriod = -1
    24  
    25  	// CachePeriodNeverValue is the string value indicating that something should not be cached
    26  	CachePeriodNeverValue string = "never"
    27  )
    28  
    29  // String returns a human-readable value for this period.
    30  func (c CachePeriod) String() string {
    31  	if c == CachePeriodForever {
    32  		return CachePeriodForeverValue
    33  	} else if c < 0 {
    34  		return CachePeriodNeverValue
    35  	}
    36  
    37  	return time.Duration(c).String()
    38  }
    39  
    40  // Next returns time after a given, base time when
    41  // the period has elapsed
    42  func (c CachePeriod) Next(base time.Time) time.Time {
    43  	return base.Add(time.Duration(c))
    44  }
    45  
    46  // MarshalJSON provides the custom JSON format for a cache period.
    47  func (c CachePeriod) MarshalJSON() (data []byte, err error) {
    48  	if c == CachePeriodForever {
    49  		data = []byte(`"` + CachePeriodForeverValue + `"`)
    50  	} else if c < 0 {
    51  		data = []byte(`"` + CachePeriodNeverValue + `"`)
    52  	} else {
    53  		data = []byte(`"` + time.Duration(c).String() + `"`)
    54  	}
    55  
    56  	return
    57  }
    58  
    59  // UnmarshalJSON parses the custom JSON format for a cache period.
    60  // Raw integers are interpreted as seconds.
    61  func (c *CachePeriod) UnmarshalJSON(data []byte) error {
    62  	var value string
    63  	if data[0] == '"' {
    64  		value = string(data[1 : len(data)-1])
    65  	} else {
    66  		value = string(data)
    67  	}
    68  
    69  	if value == CachePeriodForeverValue {
    70  		*c = CachePeriodForever
    71  		return nil
    72  	} else if value == CachePeriodNeverValue {
    73  		*c = CachePeriodNever
    74  		return nil
    75  	}
    76  
    77  	// first, try to parse the value as a time.Duration
    78  	if duration, err := time.ParseDuration(value); err == nil {
    79  		*c = CachePeriod(duration)
    80  		return nil
    81  	}
    82  
    83  	// next, try to parse the value as a number of seconds
    84  	seconds, err := strconv.ParseInt(value, 10, 64)
    85  	if err != nil {
    86  		return fmt.Errorf("Invalid cache period %s: %v", string(data), err)
    87  	}
    88  
    89  	if seconds < 0 {
    90  		*c = CachePeriodNever
    91  	} else if seconds == 0 {
    92  		*c = CachePeriodForever
    93  	} else {
    94  		*c = CachePeriod(time.Second * time.Duration(seconds))
    95  	}
    96  
    97  	return nil
    98  }