blob: 6d51cd8f62316ec8144e8f7426b7d4576cb7c7b3 [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package statefun
import (
"fmt"
"log"
"regexp"
"time"
)
type expirationType int
const (
none expirationType = iota
expireAfterCall
expireAfterWrite
)
func (e expirationType) String() string {
switch e {
case expireAfterCall:
return "expire_after_call"
case expireAfterWrite:
return "expire_after_write"
case none:
return "none"
default:
panic("unknown Expiration type")
}
}
// Expiration Configuration
//
// Defines the way state can be auto expired by the runtime.
// State Expiration (also known as TTL) can be used to keep
// state from growing arbitrarily by assigning an Expiration
// date to a value.
//
// State can be expired after a duration has passed since either
// the last write to the state, or the last call to the Function.
type Expiration struct {
expirationType
duration time.Duration
}
func (e Expiration) String() string {
return fmt.Sprintf("Expiration{mode=%v, duration=%v}", e.expirationType.String(), e.duration.String())
}
// ExpireAfterCall returns an Expiration configuration that would expire
// a duration after the last invocation of the Function.
func ExpireAfterCall(duration time.Duration) Expiration {
return Expiration{
expireAfterCall,
duration,
}
}
// ExpireAfterWrite returns an Expiration configuration that
// would expire a duration after the last write.
func ExpireAfterWrite(duration time.Duration) Expiration {
return Expiration{
expireAfterWrite,
duration,
}
}
// A ValueSpec identifies a registered persistent value of a function, which will be
// managed by the Stateful Functions runtime for consistency and fault-tolerance. A
// ValueSpec is registered for a function by configuring it on the function's
// associated StatefulFunctionSpec.
type ValueSpec struct {
// The given tpe of the persistent value. The tpe must be a valid
// identifier conforming to the following rules:
//
// 1. First character must be an alphabet letter [a-z] / [A-Z], or an underscore '_'.
// 2. Remaining characters can be an alphabet letter [a-z] / [A-Z], a digit [0-9], or
// an underscore '-'.
// 3. Must not contain any spaces.
Name string
// The SimpleType of the persistent value. Either
// a built-in PrimitiveType or custom implementation.
ValueType SimpleType
// An optional expiration configuration.
Expiration Expiration
}
func (v *ValueSpec) String() string {
return "ValueSpec{name=" + v.Name + ", type=" + v.ValueType.GetTypeName().String() + ", expiration=" + v.Expiration.String() + "}"
}
const invalidNameMessage = `
invalid state tpe %s. state names can only start with alphabet letters [a-z][A-Z] or an underscore '_' followed by zero or more characters that are alphanumeric or underscores
`
func validateValueSpec(s ValueSpec) error {
matched, err := regexp.MatchString("^[a-zA-Z_][a-zA-Z_\\d]*$", s.Name)
if err != nil {
log.Panicf("invalid regex; this is a bug: %v", err)
}
if !matched {
return fmt.Errorf(invalidNameMessage, s.Name)
}
return nil
}