mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-11 18:16:24 +05:00
added rating profile history handler
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -55,6 +55,7 @@ func (ms *MapStorage) GetRatingProfile(key string) (rp *RatingProfile, err error
|
||||
func (ms *MapStorage) SetRatingProfile(rp *RatingProfile) (err error) {
|
||||
result, err := ms.ms.Marshal(rp)
|
||||
ms.dict[RATING_PROFILE_PREFIX+rp.Id] = result
|
||||
go historyScribe.Record(RATING_PROFILE_PREFIX+rp.Id, rp)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -70,7 +71,7 @@ func (ms *MapStorage) GetDestination(key string) (dest *Destination, err error)
|
||||
func (ms *MapStorage) SetDestination(dest *Destination) (err error) {
|
||||
result, err := ms.ms.Marshal(dest)
|
||||
ms.dict[DESTINATION_PREFIX+dest.Id] = result
|
||||
historyScribe.Record(dest.Id, dest)
|
||||
go historyScribe.Record(DESTINATION_PREFIX+dest.Id, dest)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -21,9 +21,8 @@ package engine
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"menteslibres.net/gosexy/redis"
|
||||
//"log"
|
||||
"github.com/cgrates/cgrates/utils"
|
||||
"menteslibres.net/gosexy/redis"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -25,80 +25,145 @@ import (
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
const (
|
||||
DESTINATIONS_FILE = "destinations.json"
|
||||
RATING_PROFILES_FILE = "rating_profiles.json"
|
||||
)
|
||||
|
||||
type FileScribe struct {
|
||||
sync.RWMutex
|
||||
filename string
|
||||
records records
|
||||
fileRoot string
|
||||
gitCommand string
|
||||
destinations records
|
||||
ratingProfiles records
|
||||
}
|
||||
|
||||
func NewFileScribe(filename string) (Scribe, error) {
|
||||
func NewFileScribe(fileRoot string) (Scribe, error) {
|
||||
// looking for git
|
||||
_, err := exec.LookPath("git")
|
||||
gitCommand, err := exec.LookPath("git")
|
||||
if err != nil {
|
||||
return nil, errors.New("Please install git: " + err.Error())
|
||||
}
|
||||
s := &FileScribe{filename: filename}
|
||||
return s, s.load()
|
||||
s := &FileScribe{fileRoot: fileRoot, gitCommand: gitCommand}
|
||||
s.gitInit()
|
||||
if err := s.load(DESTINATIONS_FILE); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := s.load(RATING_PROFILES_FILE); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return s, nil
|
||||
}
|
||||
|
||||
func (s *FileScribe) Record(key string, obj interface{}) error {
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
s.records = s.records.SetOrAdd(key, obj)
|
||||
s.save()
|
||||
switch {
|
||||
case strings.HasPrefix(key, DESTINATION_PREFIX):
|
||||
s.destinations = s.destinations.SetOrAdd(key, obj)
|
||||
s.save(DESTINATIONS_FILE)
|
||||
case strings.HasPrefix(key, RATING_PROFILE_PREFIX):
|
||||
s.ratingProfiles = s.ratingProfiles.SetOrAdd(key, obj)
|
||||
s.save(RATING_PROFILES_FILE)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *FileScribe) commit() error {
|
||||
out, err := exec.Command("git", "commit", "-a", "-m", "'historic commit'").Output()
|
||||
if err != nil {
|
||||
func (s *FileScribe) gitInit() error {
|
||||
if _, err := os.Stat(filepath.Join(s.fileRoot, ".git")); os.IsNotExist(err) {
|
||||
cmd := exec.Command(s.gitCommand, "init")
|
||||
cmd.Dir = s.fileRoot
|
||||
if out, err := cmd.Output(); err != nil {
|
||||
return errors.New(string(out) + " " + err.Error())
|
||||
}
|
||||
if f, err := os.Create(filepath.Join(s.fileRoot, DESTINATIONS_FILE)); err != nil {
|
||||
return err
|
||||
} else {
|
||||
f.Close()
|
||||
}
|
||||
if f, err := os.Create(filepath.Join(s.fileRoot, RATING_PROFILES_FILE)); err != nil {
|
||||
return err
|
||||
} else {
|
||||
f.Close()
|
||||
}
|
||||
cmd = exec.Command(s.gitCommand, "add")
|
||||
cmd.Dir = s.fileRoot
|
||||
if out, err := cmd.Output(); err != nil {
|
||||
return errors.New(string(out) + " " + err.Error())
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *FileScribe) gitCommit() error {
|
||||
cmd := exec.Command(s.gitCommand, "commit", "-a", "-m", "'historic commit'")
|
||||
cmd.Dir = s.fileRoot
|
||||
if out, err := cmd.Output(); err != nil {
|
||||
return errors.New(string(out) + " " + err.Error())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *FileScribe) load() error {
|
||||
f, err := os.Open(s.filename)
|
||||
func (s *FileScribe) load(filename string) error {
|
||||
f, err := os.Open(filepath.Join(s.fileRoot, filename))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
d := json.NewDecoder(f)
|
||||
|
||||
if err := d.Decode(&s.records); err != nil {
|
||||
return err
|
||||
switch {
|
||||
case filename == DESTINATIONS_FILE:
|
||||
if err := d.Decode(&s.destinations); err != nil {
|
||||
return err
|
||||
}
|
||||
s.destinations.Sort()
|
||||
case filename == RATING_PROFILES_FILE:
|
||||
if err := d.Decode(&s.ratingProfiles); err != nil {
|
||||
return err
|
||||
}
|
||||
s.ratingProfiles.Sort()
|
||||
}
|
||||
s.records.Sort()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *FileScribe) save() error {
|
||||
f, err := os.Create(s.filename)
|
||||
func (s *FileScribe) save(filename string) error {
|
||||
f, err := os.Create(filepath.Join(s.fileRoot, filename))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
b := bufio.NewWriter(f)
|
||||
defer b.Flush()
|
||||
if err := s.format(b); err != nil {
|
||||
return err
|
||||
switch {
|
||||
case filename == DESTINATIONS_FILE:
|
||||
if err := s.format(b, s.destinations); err != nil {
|
||||
return err
|
||||
}
|
||||
case filename == RATING_PROFILES_FILE:
|
||||
if err := s.format(b, s.ratingProfiles); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return s.commit()
|
||||
|
||||
return s.gitCommit()
|
||||
}
|
||||
|
||||
func (s *FileScribe) format(b io.Writer) error {
|
||||
s.records.Sort()
|
||||
func (s *FileScribe) format(b io.Writer, recs records) error {
|
||||
recs.Sort()
|
||||
b.Write([]byte("["))
|
||||
for i, r := range s.records {
|
||||
for i, r := range recs {
|
||||
src, err := json.Marshal(r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
b.Write(src)
|
||||
if i < len(s.records)-1 {
|
||||
if i < len(recs)-1 {
|
||||
b.Write([]byte("\n"))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,13 +23,16 @@ import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type MockScribe struct {
|
||||
sync.RWMutex
|
||||
records records
|
||||
Buf bytes.Buffer
|
||||
destinations records
|
||||
ratingProfiles records
|
||||
DestBuf bytes.Buffer
|
||||
RpBuf bytes.Buffer
|
||||
}
|
||||
|
||||
func NewMockScribe() (Scribe, error) {
|
||||
@@ -39,31 +42,48 @@ func NewMockScribe() (Scribe, error) {
|
||||
func (s *MockScribe) Record(key string, obj interface{}) error {
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
s.records = s.records.SetOrAdd(key, obj)
|
||||
s.save()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *MockScribe) save() error {
|
||||
s.Buf.Reset()
|
||||
b := bufio.NewWriter(&s.Buf)
|
||||
defer b.Flush()
|
||||
if err := s.format(b); err != nil {
|
||||
return err
|
||||
switch {
|
||||
case strings.HasPrefix(key, DESTINATION_PREFIX):
|
||||
s.destinations = s.destinations.SetOrAdd(key[len(DESTINATION_PREFIX):], obj)
|
||||
s.save(DESTINATIONS_FILE)
|
||||
case strings.HasPrefix(key, RATING_PROFILE_PREFIX):
|
||||
s.ratingProfiles = s.ratingProfiles.SetOrAdd(key[len(DESTINATION_PREFIX):], obj)
|
||||
s.save(RATING_PROFILES_FILE)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *MockScribe) format(b io.Writer) error {
|
||||
s.records.Sort()
|
||||
func (s *MockScribe) save(filename string) error {
|
||||
switch {
|
||||
case filename == DESTINATIONS_FILE:
|
||||
s.DestBuf.Reset()
|
||||
b := bufio.NewWriter(&s.DestBuf)
|
||||
defer b.Flush()
|
||||
if err := s.format(b, s.destinations); err != nil {
|
||||
return err
|
||||
}
|
||||
case filename == RATING_PROFILES_FILE:
|
||||
s.RpBuf.Reset()
|
||||
b := bufio.NewWriter(&s.RpBuf)
|
||||
defer b.Flush()
|
||||
if err := s.format(b, s.ratingProfiles); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *MockScribe) format(b io.Writer, recs records) error {
|
||||
recs.Sort()
|
||||
b.Write([]byte("["))
|
||||
for i, r := range s.records {
|
||||
for i, r := range recs {
|
||||
src, err := json.Marshal(r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
b.Write(src)
|
||||
if i < len(s.records)-1 {
|
||||
if i < len(recs)-1 {
|
||||
b.Write([]byte("\n"))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,11 @@ import (
|
||||
"sort"
|
||||
)
|
||||
|
||||
const (
|
||||
RATING_PROFILE_PREFIX = "rpf_"
|
||||
DESTINATION_PREFIX = "dst_"
|
||||
)
|
||||
|
||||
type Scribe interface {
|
||||
Record(key string, obj interface{}) error
|
||||
}
|
||||
|
||||
@@ -97,10 +97,11 @@ func Round(x float64, prec int, method string) float64 {
|
||||
}
|
||||
|
||||
func ParseDate(date string) (expDate time.Time, err error) {
|
||||
date = strings.TrimSpace(date)
|
||||
switch {
|
||||
case date == "*unlimited" || date == "":
|
||||
// leave it at zero
|
||||
case string(date[0]) == "+":
|
||||
case strings.HasPrefix(date, "+"):
|
||||
d, err := time.ParseDuration(date[1:])
|
||||
if err != nil {
|
||||
return expDate, err
|
||||
@@ -108,7 +109,7 @@ func ParseDate(date string) (expDate time.Time, err error) {
|
||||
expDate = time.Now().Add(d)
|
||||
case date == "*monthly":
|
||||
expDate = time.Now().AddDate(0, 1, 0) // add one month
|
||||
case strings.Contains(date, "Z"):
|
||||
case strings.HasSuffix(date, "Z"):
|
||||
expDate, err = time.Parse(time.RFC3339, date)
|
||||
default:
|
||||
unix, err := strconv.ParseInt(date, 10, 64)
|
||||
|
||||
Reference in New Issue
Block a user