orm

package module
v1.51.15 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 5, 2020 License: MIT Imports: 37 Imported by: 1

README

orm

codecov Go Report Card MIT license

ORM that delivers support for full stack data access:

  • MySQL - for relational data
  • Redis - for NoSQL in memory shared cache
  • Elastic Search - for full text search
  • Local Cache - in memory local (not shared) cache
  • ClickHouse - time series database
  • RabbitMQ - message broker
  • DataDog - monitoring

Menu:

Configuration

First you need to define Registry object and register all connection pools to MySQL, Redis, RabbitMQ and local cache. Use this object to register queues, and entities. You should create this object once when application starts.

package main

import "github.com/summer-solutions/orm"

func main() {

    registry := &Registry{}

    /*MySQL */
    registry.RegisterMySQLPool("root:root@tcp(localhost:3306)/database_name")
    //optionally you can define pool name as second argument
    registry.RegisterMySQLPool("root:root@tcp(localhost:3307)/database_name", "second_pool")

    /* Redis */
    registry.RegisterRedis("localhost:6379", 0)
    //optionally you can define pool name as second argument
    registry.RegisterRedis("localhost:6379", 1, "second_pool")

    /* Redis ring */
    registry.RegisterRedisRing([]string{"localhost:6379", "localhost:6380"}, 0)

    /* RabbitMQ */
    registry.RegisterRabbitMQServer("amqp://rabbitmq_user:rabbitmq_password@localhost:5672/")
    registry.RegisterRabbitMQQueue(&RabbitMQQueueConfig{Name: "test_queue"})
    registry.RegisterRabbitMQRouter(&RabbitMQRouterConfig{Name, "test_router"})

    /* Local cache (in memory) */
    registry.RegisterLocalCache(1000) //you need to define cache size
    //optionally you can define pool name as second argument
    registry.RegisterLocalCache(100, "second_pool")

    /* Redis used to handle locks (explained later) */
    registry.RegisterRedis("localhost:6379", 4, "lockers_pool")
    registry.RegisterLocker("default", "lockers_pool")

    /* ElasticSearch */
    registry.RegisterElastic("http://127.0.0.1:9200")
    //optionally you can define pool name as second argument
    registry.RegisterElastic("http://127.0.0.1:9200", "second_pool")
    // you can enable trace log
    registry.RegisterElasticWithTraceLog("http://127.0.0.1:9200", "second_pool")

    /* ClickHouse */
    registry.RegisterClickHouse("http://127.0.0.1:9000")
    //optionally you can define pool name as second argument
    registry.RegisterClickHouse("http://127.0.0.1:9000", "second_pool")
}

You can also create registry using yaml configuration file:
default:
    mysql: root:root@tcp(localhost:3310)/db
    redis: localhost:6379:0
    elastic: http://127.0.0.1:9200
    elastic_trace: http://127.0.0.1:9201 //with trace log
    clickhouse: http://127.0.0.1:9000
    locker: default
    dirty_queues:
        test: 10
        test2: 1    
    local_cache: 1000
    rabbitmq:
        server: amqp://rabbitmq_user:rabbitmq_password@localhost:5672/
        queues:
            - name: test
            - name: test2
              durrable: false // optional, default true
              autodelete: false // optional, default false
              prefetchCount: 1 // optional, default 1
              router: test_router // optional, default ""
              ttl: 60 //optional, as seconds, defalut 0 - no TTL  
              router_keys: // optional, default []string
                - aa
                - bb
        routers:
            - name: test_router
              type: direct  
              durable: false // optional, default true
second_pool:
    mysql: root:root@tcp(localhost:3311)/db2
    redis:  // redis ring
        - localhost:6380:0
        - localhost:6381
        - localhost:6382
package main

import (
    "github.com/summer-solutions/orm"
    "gopkg.in/yaml.v2"
    "io/ioutil"
)

func main() {

    yamlFileData, err := ioutil.ReadFile("./yaml")
    if err != nil {
        //...
    }
    
    var parsedYaml map[string]interface{}
    err = yaml.Unmarshal(yamlFileData, &parsedYaml)
    registry := InitByYaml(parsedYaml)
}

Defining entities

package main

import (
	"github.com/summer-solutions/orm"
	"time"
)

func main() {

    type AddressSchema struct {
        Street   string
        Building uint16
    }
    
    type colors struct {
        Red    string
        Green  string
        Blue   string
        Yellow string
        Purple string
    }
    var Colors = &colors{
        orm.EnumModel,
    	Red:    "Red",
    	Green:  "Green",
    	Blue:   "Blue",
    	Yellow: "Yellow",
    	Purple: "Purple",
    }

    type testEntitySchema struct {
        orm.ORM
        ID                   uint
        Name                 string `orm:"length=100;index=FirstIndex"`
        NameNullable         string `orm:"length=100;index=FirstIndex"`
        BigName              string `orm:"length=max;required"`
        Uint8                uint8  `orm:"unique=SecondIndex:2,ThirdIndex"`
        Uint24               uint32 `orm:"mediumint=true"`
        Uint32               uint32
        Uint32Nullable       *uint32
        Uint64               uint64 `orm:"unique=SecondIndex"`
        Int8                 int8
        Int16                int16
        Int32                int32
        Int64                int64
        Rune                 rune
        Int                  int
        IntNullable          *int
        Bool                 bool
        BoolNullable         *bool
        Float32              float32
        Float64              float64
        Float64Nullable      *float64
        Float32Decimal       float32  `orm:"decimal=8,2"`
        Float64DecimalSigned float64  `orm:"decimal=8,2;unsigned=false"`
        Enum                 string   `orm:"enum=orm.colorEnum"`
        EnumNotNull          string   `orm:"enum=orm.colorEnum;required"`
        Set                  []string `orm:"set=orm.colorEnum"`
        YearNullable         *uint16   `orm:"year=true"`
        YearNotNull          uint16   `orm:"year=true"`
        Date                 *time.Time
        DateNotNull          time.Time
        DateTime             *time.Time `orm:"time=true"`
        DateTimeNotNull      time.Time  `orm:"time=true"`
        Address              AddressSchema
        Json                 interface{}
        ReferenceOne         *testEntitySchemaRef
        ReferenceOneCascade  *testEntitySchemaRef `orm:"cascade"`
        ReferenceMany        []*testEntitySchemaRef
        IgnoreField          []time.Time       `orm:"ignore"`
        Blob                 []byte
        MediumBlob           []byte `orm:"mediumblob=true"`
        LongBlob             []byte `orm:"longblob=true"`
        FieldAsJson          map[string]string
    }
    
    type testEntitySchemaRef struct {
        orm.ORM
        ID   uint
        Name string
    }
    type testEntitySecondPool struct {
    	orm.ORM `orm:"mysql=second_pool"`
    	ID                   uint
    }

    registry := &Registry{}
    var testEntitySchema testEntitySchema
    var testEntitySchemaRef testEntitySchemaRef
    var testEntitySecondPool testEntitySecondPool
    registry.RegisterEntity(testEntitySchema, testEntitySchemaRef, testEntitySecondPool)
    registry.RegisterEnumStruct("color", Colors)

    // now u can use:
    Colors.GetDefault() // "Red" (first field)
    Colors.GetFields() // ["Red", "Blue" ...]
    Colors.GetMapping() // map[string]string{"Red": "Red", "Blue": "Blue"}
    Colors.Has("Red") //true
    Colors.Has("Orange") //false
    
    //or register enum from slice
    registry.RegisterEnumSlice("color", []string{"Red", "Blue"})
    validatedRegistry.GetEnum("color").GetFields()
    validatedRegistry.GetEnum("color").Has("Red")
    
    //or register enum from map
    registry.RegisterEnumMap("color", map[string]string{"red": "Red", "blue": "Blue"}, "red")
}

There are only two golden rules you need to remember defining entity struct:

  • first field must be type of "ORM"
  • second argument must have name "ID" and must be type of one of uint, uint16, uint32, uint24, uint64, rune

By default entity is not cached in local cache or redis, to change that simply use key "redisCache" or "localCache" in "orm" tag for "ORM" field:

package main

import (
	"github.com/summer-solutions/orm"
	"time"
)

func main() {

    type testEntityLocalCache struct {
    	orm.ORM `orm:"localCache"` //default pool
       //...
    }
   
   type testEntityLocalCacheSecondPool struct {
    	orm.ORM `orm:"localCache=second_pool"`
       //...
    }
   
   type testEntityRedisCache struct {
    	orm.ORM `orm:"redisCache"` //default pool
       //...
    }
   
   type testEntityRedisCacheSecondPool struct {
    	orm.ORM `orm:"redisCache=second_pool"`
       //...
    }

   type testEntityLocalAndRedisCache struct {
    	orm.ORM `orm:"localCache;redisCache"`
       //...
    }
}

Validated registry

Once you created your registry and registered all pools and entities you should validate it. You should also run it once when your application starts.

package main

import "github.com/summer-solutions/orm"

func main() {
   registry := &Registry{}
   //register pools and entities
   validatedRegistry, err := registry.Validate()
}

Creating engine

You need to crete engine to start working with entities (searching, saving). You must create engine for each http request and thread.

package main

import "github.com/summer-solutions/orm"

func main() {
   registry := &Registry{}
   //register pools and entities
   validatedRegistry, err := registry.Validate()
   engine := validatedRegistry.CreateEngine()
}

Checking and updating table schema

ORM provides useful object that describes entity structrure called TabelSchema:

package main

import "github.com/summer-solutions/orm"

func main() {
   
   registry := &Registry{}
   // register
   validatedRegistry, err := registry.Validate() 
   engine := validatatedRegistry.CreateEngine()
   alters := engine.GetAlters()
   
   /*optionally you can execute alters for each model*/
   var userEntity UserEntity
   tableSchema := engine.GetRegistry().GetTableSchemaForEntity(userEntity)
   //or
   tableSchema := validatedRegistry.GetTableSchemaForEntity(userEntity)

   /*checking table structure*/
   tableSchema.UpdateSchema(engine) //it will create or alter table if needed
   tableSchema.DropTable(engine) //it will drop table if exist
   tableSchema.TruncateTable(engine)
   tableSchema.UpdateSchemaAndTruncateTable(engine)
   has, alters := tableSchema.GetSchemaChanges(engine)

   /*getting table structure*/
   db := tableSchema.GetMysql(engine)
   localCache, has := tableSchema.GetLocalCache(engine) 
   redisCache, has := tableSchema.GetRedisCache(engine)
   columns := tableSchema.GetColumns()
   tableSchema.GetTableName()
}

Adding, editing, deleting entities

package main

import "github.com/summer-solutions/orm"

func main() {

     /* adding */

    entity := testEntity{Name: "Name 1"}
    engine.TrackAndFlush(&entity)

    entity2 := testEntity{Name: "Name 1"}
    engine.SetOnDuplicateKeyUpdate(NewWhere("`counter` = `counter` + 1"), entity2)
    engine.TrackAndFlush(&entity)

    entity2 = testEntity{Name: "Name 1"}
    engine.SetOnDuplicateKeyUpdate(NewWhere(""), entity2) //it will change nothing un row
    engine.TrackAndFlush(&entity)

    /*if you need to add more than one entity*/
    entity = testEntity{Name: "Name 2"}
    entity2 := testEntity{Name: "Name 3"}
    engine.Track(&entity, &entity2) //it will also automatically run RegisterEntity()
    //it will execute only one query in MySQL adding two rows at once (atomic)
    engine.Flush()
 
    /* editing */

    engine.Track(&entity, &entity2)
    entity.Name = "New name 2"
    //you can also use (but it's slower):
    entity.SetField("Name", "New name 2")
    engine.IsDirty(entity) //returns true
    engine.IsDirty(entity2) //returns false
    entity.Flush() //it will save data in DB for all dirty tracked entities and untrack all of them
    engine.IsDirty(entity) //returns false
    
    /* deleting */
    engine.MarkToDelete(entity2)
    engine.IsDirty(entity2) //returns true
    engine.Flush()

    /* flush will panic if there is any error. You can catch 2 special errors using this method  */
    err := engine.FlushWithCheck()
    //or
    err := engine.FlushInTransactionWithCheck()
    orm.DuplicatedKeyError{} //when unique index is broken
    orm.ForeignKeyError{} //when foreign key is broken
    
    /* You can catch all errors using this method  */
    err := engine.FlushWithFullCheck()
}

Transactions

package main

import "github.com/summer-solutions/orm"

func main() {
	
    entity = testEntity{Name: "Name 2"}
    entity2 := testEntity{Name: "Name 3"}
    engine.Track(&entity, &entity2)

    // DB transcation
    engine.FlushInTransaction()
    // or redis lock
    engine.FlushWithLock("default", "lock_name", 10 * time.Second, 10 * time.Second)
    // or DB transcation nad redis lock
    engine.FlushInTransactionWithLock("default", "lock_name", 10 * time.Second, 10 * time.Second)
 
    //manual transaction
    db := engine.GetMysql()
    db.Begin()
    defer db.Rollback()
    //run queries
    db.Commit()

Loading entities using primary key

package main

import "github.com/summer-solutions/orm"

func main() {

    var entity testEntity
    has := engine.LoadByID(1, &entity)

    var entities []*testEntity
    missing := engine.LoadByIDs([]uint64{1, 3, 4}, &entities) //missing contains IDs that are missing in database

}

package main

import "github.com/summer-solutions/orm"

func main() {

    var entities []*testEntity
    pager := orm.NewPager(1, 1000)
    where := orm.NewWhere("`ID` > ? AND `ID` < ?", 1, 8)
    engine.Search(where, pager, &entities)
    
    //or if you need number of total rows
    totalRows := engine.SearchWithCount(where, pager, &entities)
    
    //or if you need only one row
    where := onm.NewWhere("`Name` = ?", "Hello")
    var entity testEntity
    found := engine.SearchOne(where, &entity)
    
    //or if you need only primary keys
    ids := engine.SearchIDs(where, pager, entity)
    
    //or if you need only primary keys and total rows
    ids, totalRows = engine.SearchIDsWithCount(where, pager, entity)
}

Reference one to one

package main

import "github.com/summer-solutions/orm"

func main() {

    type UserEntity struct {
        ORM
        ID                   uint64
        Name                 string
        School               *SchoolEntity `orm:"required"` // key is "on delete restrict" by default not not nullable
        SecondarySchool      *SchoolEntity // key is nullable
    }
    
    type SchoolEntity struct {
        ORM
        ID                   uint64
        Name                 string
    }

    type UserHouse struct {
        ORM
        ID                   uint64
        User                 *UserEntity  `orm:"cascade;required"` // on delete cascade and is not nullable
    }
    
    // saving in DB:

    user := UserEntity{Name: "John"}
    school := SchoolEntity{Name: "Name of school"}
    house := UserHouse{Name: "Name of school"}
    engine.Track(&user, &school, &house)
    user.School = school
    house.User = user
    engine.Flush()

    // loading references: 

    _ = engine.LoadById(1, &user)
    user.School != nil //returns true, School has ID: 1 but other fields are nof filled
    user.School.ID == 1 //true
    user.School.Loaded() //false
    user.Name == "" //true
    user.School.Load(engine) //it will load school from db
    user.School.Loaded() //now it's true, you can access school fields like user.School.Name
    user.Name == "Name of school" //true
    
    //If you want to set reference and you have only ID:
    user.School = &SchoolEntity{ID: 1}

    // detaching reference
    user.School = nil

    // preloading references
    engine.LoadByID(1, &user, "*") //all references
    engine.LoadByID(1, &user, "School") //only School
    engine.LoadByID(1, &user, "School", "SecondarySchool") //only School and SecondarySchool
    engine.LoadByID(1, &userHouse, "User/School", "User/SecondarySchool") //User, School and SecondarySchool in each User
    engine.LoadByID(1, &userHouse, "User/*") // User, all references in User
    engine.LoadByID(1, &userHouse, "User/*/*") // User, all references in User and all references in User subreferences
    //You can have as many levels you want: User/School/AnotherReference/EvenMore/
    
    //You can preload referenes in all search and load methods:
    engine.LoadByIDs()
    engine.Search()
    engine.SearchOne()
    engine.CachedSearch()
    ...
}

Cached queries

package main

import "github.com/summer-solutions/orm"

func main() {

    //Fields that needs to be tracked for changes should start with ":"

    type UserEntity struct {
        ORM
        ID                   uint64
        Name                 string
        Age                  uint16
        IndexAge             *CachedQuery `query:":Age = ? ORDER BY :ID"`
        IndexAll             *CachedQuery `query:""` //cache all rows
        IndexName            *CachedQuery `queryOne:":Name = ?"`
    }

    pager := orm.NewPager(1, 1000)
    var users []*UserEntity
    var user  UserEntity
    totalRows := engine.CachedSearch(&users, "IndexAge", pager, 18)
    totalRows = engine.CachedSearch(&users, "IndexAll", pager)
    has := engine.CachedSearchOne(&user, "IndexName", "John")

}

Lazy flush

Sometimes you want to flush changes in database, but it's ok if data is flushed after some time. For example when you want to save some logs in database.

package main

import "github.com/summer-solutions/orm"

func main() {
    
    // you need to register default rabbitMQ server    
    registry.RegisterRabbitMQServer("amqp://rabbitmq_user:rabbitmq_password@localhost:5672/")
    
    // now in code you can use FlushLazy() methods instead of Flush().
    // it will send changes to queue (database and cached is not updated yet)
    user.FlushLazy()
    
    //You need to run code that will read data from queue and execute changes
    
    receiver := NewLazyReceiver(engine)
    //optionally 
    receiver.Digest() //It will wait for new messages in queue, run receiver.DisableLoop() to run loop once
}

Log entity changes

ORM can store in database every change of entity in special log table.

package main

import "github.com/summer-solutions/orm"

func main() {

    //it's recommended to keep logs in separated DB
    registry.RegisterMySQLPool("root:root@tcp(localhost:3306)/log_database", "log_db_pool")
    // you need to register default rabbitMQ server    
    registry.RegisterRabbitMQServer("amqp://rabbitmq_user:rabbitmq_password@localhost:5672/")

    //next you need to define in Entity that you want to log changes. Just add "log" tag
    type User struct {
        ORM  `orm:"log=log_db_pool"`
        ID   uint
        Name string
        Age  int `orm:"skip-log"` //Don't track this field
    }

    // Now every change of User will be saved in log table
   
    
    // You can add extra data to log, simply use this methods before Flush():
    engine.SetLogMetaData("logged_user_id", 12) 
    engine.SetLogMetaData("ip", request.GetUserIP())
    // you can set meta only in specific entity
    engine.SetEntityLogMeta("user_name", "john", entity)
    
    receiver := NewLogReceiver(engine)
    receiver.Digets() //it will wait for new messages in queue
}

Dirty queues

You can send event to queue if any specific data in entity was changed.

package main

import "github.com/summer-solutions/orm"

func main() {
    
    registry.RegisterRabbitMQServer("amqp://rabbitmq_user:rabbitmq_password@localhost:5672/")
    // register dirty queue
    registry.RegisterDirtyQueue("user_changed", 100)
    registry.RegisterDirtyQueue("age_name_changed", 100)
    registry.RegisterDirtyQueue("age_changed", 100)

    // next you need to define in Entity that you want to log changes. Just add "log" tag
    type User struct {
        orm.ORM  `orm:"dirty=user_changed"` //define dirty here to track all changes
        ID       uint
        Name     string `orm:"dirty=age_name_changed"` //event will be send to age_name_changed if Name or Age changed
        Age      int `orm:"dirty=age_name_changed,age_changed"` //event will be send to age_changed if Age changed
    }

    // now just use Flush and events will be send to queue

    // receiving events
    receiver := NewDirtyReceiver(engine)
    
    // in this case data length is max 100
    receiver.Digest("user_changed", func(data []*DirtyData) {
        for _, item := range data {
            // data.TableSchema is TableSchema of entity
            // data.ID has entity ID
            // data.Added is true if entity was added
            // data.Updated is true if entity was updated
            // data.Deleted is true if entity was deleted
        }
    })
}


Fake delete

If you want to keep deleted entity in database but ny default this entity should be excluded from all engine.Search() and engine.CacheSearch() queries you can use FakeDelete column. Simply create field bool with name "FakeDelete".

func main() {

    type UserEntity struct {
        ORM
        ID                   uint64
        Name                 string
        FakeDelete           bool
    }

    //you can delete in two ways:
    engine.MarkToDelete(user) -> will set user.FakeDelete = true
    //or:
    user.FakeDelete = true

    engine.Flush(user) //it will save entity id in Column `FakeDelete`.

    //will return all rows where `FakeDelete` = 0
    total, err = engine.SearchWithCount(NewWhere("1"), nil, &rows)

    //To force delete (remove row from DB):
    engine.ForceMarkToDelete(user)
    engine.Flush(user)
}


Working with Redis

package main

import "github.com/summer-solutions/orm"

func main() {

    config.RegisterRedis("localhost:6379", 0)
    
    //storing data in cached for x seconds
    val := engine.GetRedis().GetSet("key", 1, func() interface{} {
		return "hello"
	})
    
    //standard redis api
    keys := engine.GetRedis().LRange("key", 1, 2)
    engine.GetRedis().LPush("key", "a", "b")
    //...

    //rete limiter
    valid := engine.GetRedis().RateLimit("resource_name", redis_rate.PerMinute(10))
}

Working with local cache

package main

import "github.com/summer-solutions/orm"

func main() {
    
    registry.RegisterLocalCache(1000)
    
    //storing data in cached for x seconds
    val := engine.GetLocalCache().GetSet("key", 1, func() interface{} {
        return "hello"
    })
    
    //getting value
    value, has := engine.GetLocalCache().Get("key")
    
    //getting many values
    values := engine.GetLocalCache().MGet("key1", "key2")
    
    //setting value
    engine.GetLocalCache().Set("key", "value")
    
    //setting values
    engine.GetLocalCache().MSet("key1", "value1", "key2", "value2" /*...*/)
    
    //getting values from hash set (like redis HMGET)
    values = engine.GetLocalCache().HMget("key")
    
    //setting values in hash set
    engine.GetLocalCache().HMset("key", map[string]interface{}{"key1" : "value1", "key2": "value 2"})

    //deleting value
    engine.GetLocalCache().Remove("key1", "key2" /*...*/)
    
    //clearing cache
    engine.GetLocalCache().Clear()

}

Working with mysql

package main

import (
    "database/sql"
    "github.com/summer-solutions/orm"
)

func main() {
    
    // register mysql pool
    registry.RegisterMySQLPool("root:root@tcp(localhost:3306)/database_name")

    res := engine.GetMysql().Exec("UPDATE `table_name` SET `Name` = ? WHERE `ID` = ?", "Hello", 2)

    var row string
    found := engine.GetMysql().QueryRow(orm.NewWhere("SELECT * FROM `table_name` WHERE  `ID` = ?", 1), &row)
    
    results, def := engine.GetMysql().Query("SELECT * FROM `table_name` WHERE  `ID` > ? LIMIT 100", 1)
    defer def()
    for results.Next() {
    	var row string
        results.Scan(&row)
    }
    def() //if it's not last line in this method
}

package main

import (
    "github.com/summer-solutions/orm"
)

func main() {

    type TestIndex struct {
    }
    
    func (i *TestIndex) GetName() string {
    	return "test_index"
    }
    
    func (i *TestIndex) GetDefinition() map[string]interface{} {
        return map[string]interface{}{
            "settings": map[string]interface{}{
                "number_of_replicas": "1",
                "number_of_shards":   "1",
            },
            "mappings": map[string]interface{}{
                "properties": map[string]interface{}{
                    "Name": map[string]interface{}{
                        "type":       "keyword",
                        "normalizer": "case_insensitive",
                    },
                },
            },
        }
    }

    
    // register elastic search pool and index
    registry.RegisterElastic("http://127.0.0.1:9200")
    registry.RegisterElasticIndex(&TestIndex{})


    e := engine.GetElastic()

    // create indices
	for _, alter := range engine.GetElasticIndexAlters() {
        // alter.Safe is true if index does not exists or is not empty
		engine.GetElastic(alter.Pool).CreateIndex(alter.Index)
	}

    query := elastic.NewBoolQuery()
	query.Must(elastic.NewTermQuery("user_id", 12))
    options := &orm.SearchOptions{}
    options.AddSort("created_at", true).AddSort("name", false)
	results := e.Search("users", query, orm.NewPager(1, 10), options)
}

Working with ClickHouse

package main

import (
    "github.com/summer-solutions/orm"
)

func main() {
    
    // register elastic search pool
    registry.RegisterClickHouse("http://127.0.0.1:9000")

    ch := engine.GetClickHouse()

    ch.Exec("INSERT INTO `table` (name) VALUES (?)", "hello")

    statement, def := ch.Prepare("INSERT INTO `table` (name) VALUES (?)")
    defer def()
    statement.Exec("hello")
    statement.Exec("hello 2")

    rows, def := ch.Queryx("SELECT FROM `table` WHERE x = ? AND y = ?", 1, "john")
    defer def()
    for rows.Next() {
    	m := &MyStruct{}
        err := rows.StructScan(m)
    }

    ch.Begin()
    defer ch.Rollback()
    // run queries
    defer ch.Commit()
}

Working with Locker

Shared cached that is using redis

package main

import "github.com/summer-solutions/orm"

func main() {

    // register redis and locker
    registry.RegisterRedis("localhost:6379", 0, "my_pool")
    registry.RegisterLocker("default", "my_pool")
    
    locker, _ := engine.GetLocker()
    lock := locker.Obtain("my_lock", 5 * Time.Second, 1 * Time.Second)

    defer lock.Release()
    
    // do smth
    
    ttl := lock.TTL()
    if ttl == 0 {
        panic("lock lost")
    }
}

Working with RabbitMQ

package main

import "github.com/summer-solutions/orm"

func main() {

    // register rabbitMQ servers, queues and routers
    registry.RegisterRabbitMQServer("amqp://rabbitmq_user:rabbitmq_password@localhost:5672/")
    registry.RegisterRabbitMQQueue(&RabbitMQQueueConfig{Name: "test_queue", TTL: 60}) //ttl set to 60 seconds
    registry.RegisterRabbitMQQueue(&RabbitMQQueueConfig{Name: "test_queue_router", 
        Router: "test_router", RouteKeys: []string{"aa", "bb"}})
    registry.RegisterRabbitMQRoutere("default", &RabbitMQRouteConfig{Name: "test_router", Type: "fanout"})
    
    //create engine:
    validatedRegistry, err := registry.Validate()
    engine := validatedRegistry.CreateEngine()
    defer engine.Defer() //it will close all opened channels

    //Simple queue
    channel := engine.GetRabbitMQQueue("test_queue") //provide Queue name
    defer channel.Close()
    channel.Publish([]byte("hello"))

    //start consumer (you can add as many you want)
    consumer, err := channel.NewConsumer("test consumer")
    defer consumer.Close()
    consumer.Consume(func(items [][]byte) {
    	//do staff
    })

    //start consumer (you can add as many you want)
    consumer := channel.NewConsumer("test consumer")
    defer consumer.Close()
    consumer.Consume(func(items [][]byte) {
        //do staff
    })
    
    // publish to router

    channel = engine.GetRabbitMQRouter("test_queue_router") 
    defer channel.Close()
    channel.Publish("router.key", []byte("hello"))

    //start consumer
   consumer := channel.NewConsumer("test consumer")
   defer consumer.Close()
   consumer.Consume(func(items [][]byte) {
        //do staff
        return nil
   })
}

Query logging

You can log all queries:

  • queries to MySQL database (insert, select, update)
  • requests to Redis
  • requests to rabbitMQ
  • requests to Elastic Search
  • queries to CickHouse
package main

import "github.com/summer-solutions/orm"

func main() {
	
    //enable human friendly console log
    engine.EnableQueryDebug() //MySQL, redis, rabbitMQ, Elastic Search, ClickHouse queries (local cache in excluded bt default)
    engine.EnableQueryDebug(orm.QueryLoggerSourceRedis, orm.QueryLoggerSourceLocalCache)

    //adding custom logger example:
    engine.AddQueryLogger(json.New(os.Stdout), log.LevelWarn) //MySQL, redis, rabbitMQ warnings and above
    engine.AddQueryLogger(es.New(os.Stdout), log.LevelError, orm.QueryLoggerSourceRedis, orm. QueryLoggerSourceRabbitMQ)
}    

Logger

package main

import "github.com/summer-solutions/orm"

func main() {
	
    //enable json logger with proper level
    engine.EnableLogger(log.InfoLevel)
    //or enable human friendly console logger
    engine.EnableDebug()
    
    //you can add special fields to all logs
    engine.Log().AddFields(log.Fields{"user_id": 12, "session_id": "skfjhfhhs1221"})

    //printing logs
    engine.Log().Warn("message", nil)
    engine.Log().Debug("message", log.Fields{"user_id": 12})
    engine.Log().Error(err, nil)
    engine.Log().ErrorMessage("ups, that is strange", nil)


    //handling recovery
    if err := recover(); err != nil {
    	engine.Log().Error(err, nil)
    }

    //filling log with data from http.Request
    engine.Log().AddFieldsFromHTTPRequest(request, "197.21.34.22")

}    

DataDog Profiler

To enable DataDog profiler simply add two lines of code in your main function. Provide your service name, datadog API key, environment name (production, test, ..n) and interval how often system should send profiler data to Datadog

package main

import "github.com/summer-solutions/orm"

func main() {
	
    def := orm.StartDataDogProfiler("my-app-name", "DATADOG-API-KEY", "production", time.Minute)
    defer def()

}    

DataDog APM

First you need to register it in your main function

package main

import "github.com/summer-solutions/orm"

func main() {
    
   //provide rate, 1 - 100% traces are reported, 0.1 - 10% traces are reported (and all with errors)
   // if you provide zero only traces with errors will be reported
   def := orm.StartDataDogTracer(1.0) 
   defer def()

}    

Start trace for HTTP request. Example in Gin framework:

package main

import "github.com/summer-solutions/orm"

func main() {
    
    router := gin.New()
    //you should define it as first middleware
    router.Use(func(c *gin.Context) {
        engine := // create orm.Engine
        apm := engine.DataDog().StartHTTPAPM(c.Request, "my-app-name", "production")
        defer apm.Finish()
    
        //optionally enable ORM APM services
        engine.DataDog().EnableORMAPMLog(log.InfoLevel, true) //log ORM requests (MySQl, RabbitMQ, Redis queries) as services

        c.Next()
        apm.SetResponseStatus(c.Writer.Status())
    })

}    

Start trace in scripts (for example in cron scripts):

package main

import "github.com/summer-solutions/orm"

func main() {
    
    engine.DataDog().StartAPM("my-script-name", "production")
    defer engine.DataDog().FinishAPM()
    //optionally enable ORM APM services
    engine.DataDog().EnableORMAPMLog(log.InfoLevel, true)
    //execute your code
}    

Start trace in intermediate scripts:

package main

import "github.com/summer-solutions/orm"

func main() {
    
    engine := //
    engine.DataDog().StartAPM("my-script-name", "production")
    defer engine.DataDog().FinishAPM()
    engine.DataDog().EnableORMAPMLog(log.InfoLevel, true)

    heartBeat := func() {
        engine.DataDog().FinishAPM()
        engine.DataDog().StartAPM("my-script-name", "production")
    }
    receiver := orm.NewLogReceiver(engine)
    receiver.SetHeartBeat(heartBeat) //receiver will execute this method every minute
    receiver.Digest()

}    

You should always assign unexpected error to APM trace

package main

import "github.com/summer-solutions/orm"

func main() {
    
    if r := recover(); r != nil {
        engine.DataDog().RegisterAPMError(r)
    }
}    

Extra operations:

package main

import "github.com/summer-solutions/orm"

func main() {

	engine.DataDog().DropAPM() //it will drop trace. Only traces with errors will be recorded
    
    engine.DataDog().SetAPMTag("user_id", 12)
    
    //sub tasks
    func() {
    	span := engine.DataDog().StartWorkSpan("logging user")
        span.setTag("user_name", "Tom")
        defer.span.Finish()
        //some work
    }()

}    

Documentation

Index

Constants

View Source
const (
	QueryLoggerSourceDB = iota
	QueryLoggerSourceRedis
	QueryLoggerSourceRabbitMQ
	QueryLoggerSourceElastic
	QueryLoggerSourceClickHouse
	QueryLoggerSourceLocalCache
)

Variables

This section is empty.

Functions

func StartDataDogProfiler

func StartDataDogProfiler(service string, apiKey string, environment string, duration time.Duration) (def func())

func StartDataDogTracer

func StartDataDogTracer(rate float64, opts ...tracer.StartOption) (def func())

Types

type APM

type APM interface {
	Finish()
}

type Alter

type Alter struct {
	SQL  string
	Safe bool
	Pool string
}

type CachedQuery

type CachedQuery struct{}

type ClickHouse

type ClickHouse struct {
	// contains filtered or unexported fields
}

func (*ClickHouse) Begin

func (c *ClickHouse) Begin()

func (*ClickHouse) Commit

func (c *ClickHouse) Commit()

func (*ClickHouse) Exec

func (c *ClickHouse) Exec(query string, args ...interface{}) sql.Result

func (*ClickHouse) Prepare

func (c *ClickHouse) Prepare(query string) (preparedStatement *PreparedStatement, deferF func())

func (*ClickHouse) Queryx

func (c *ClickHouse) Queryx(query string, args ...interface{}) (rows *sqlx.Rows, deferF func())

func (*ClickHouse) Rollback

func (c *ClickHouse) Rollback()

type ClickHouseConfig

type ClickHouseConfig struct {
	// contains filtered or unexported fields
}

type DB

type DB struct {
	// contains filtered or unexported fields
}

func (*DB) Begin

func (db *DB) Begin()

func (*DB) Commit

func (db *DB) Commit()

func (*DB) Exec

func (db *DB) Exec(query string, args ...interface{}) ExecResult

func (*DB) GetDatabaseName

func (db *DB) GetDatabaseName() string

func (*DB) GetPoolCode

func (db *DB) GetPoolCode() string

func (*DB) Query

func (db *DB) Query(query string, args ...interface{}) (rows Rows, deferF func())

func (*DB) QueryRow

func (db *DB) QueryRow(query *Where, toFill ...interface{}) (found bool)

func (*DB) Rollback

func (db *DB) Rollback()

type DBConfig

type DBConfig struct {
	// contains filtered or unexported fields
}

type DataDog

type DataDog interface {
	StartAPM(service string, environment string)
	FinishAPM()
	StartHTTPAPM(request *http.Request, service string, environment string) HTTPAPM
	EnableORMAPMLog(level apexLog.Level, withAnalytics bool, source ...QueryLoggerSource)
	RegisterAPMError(err interface{})
	DropAPM()
	SetAPMTag(key string, value interface{})
	StartWorkSpan(name string) WorkSpan
}

type DirtyData

type DirtyData struct {
	TableSchema *tableSchema
	ID          uint64
	Added       bool
	Updated     bool
	Deleted     bool
}

type DirtyHandler

type DirtyHandler func(data []*DirtyData)

type DirtyQueueValue

type DirtyQueueValue struct {
	EntityName string
	ID         uint64
	Added      bool
	Updated    bool
	Deleted    bool
}

type DirtyReceiver

type DirtyReceiver struct {
	// contains filtered or unexported fields
}

func NewDirtyReceiver

func NewDirtyReceiver(engine *Engine) *DirtyReceiver

func (*DirtyReceiver) Digest

func (r *DirtyReceiver) Digest(code string, handler DirtyHandler)

func (*DirtyReceiver) DisableLoop

func (r *DirtyReceiver) DisableLoop()

func (*DirtyReceiver) Purge

func (r *DirtyReceiver) Purge(code string)

func (*DirtyReceiver) SetHeartBeat

func (r *DirtyReceiver) SetHeartBeat(beat func())

func (*DirtyReceiver) SetMaxLoopDuration

func (r *DirtyReceiver) SetMaxLoopDuration(duration time.Duration)

type DuplicatedKeyError

type DuplicatedKeyError struct {
	Message string
	Index   string
}

func (*DuplicatedKeyError) Error

func (err *DuplicatedKeyError) Error() string

type Elastic

type Elastic struct {
	// contains filtered or unexported fields
}

func (*Elastic) Client

func (e *Elastic) Client() *elastic.Client

func (*Elastic) CreateIndex

func (e *Elastic) CreateIndex(index ElasticIndexDefinition)

func (*Elastic) DropIndex

func (e *Elastic) DropIndex(index ElasticIndexDefinition)

func (*Elastic) Search

func (e *Elastic) Search(index string, query elastic.Query, pager *Pager, options *SearchOptions) *elastic.SearchResult

type ElasticConfig

type ElasticConfig struct {
	// contains filtered or unexported fields
}

type ElasticIndexAlter

type ElasticIndexAlter struct {
	Index      ElasticIndexDefinition
	Safe       bool
	Pool       string
	NewMapping map[string]interface{}
	OldMapping map[string]interface{}
}

type ElasticIndexDefinition

type ElasticIndexDefinition interface {
	GetName() string
	GetDefinition() map[string]interface{}
}

type Engine

type Engine struct {
	// contains filtered or unexported fields
}

func (*Engine) AddQueryLogger

func (e *Engine) AddQueryLogger(handler logApex.Handler, level logApex.Level, source ...QueryLoggerSource)

func (*Engine) CachedSearch

func (e *Engine) CachedSearch(entities interface{}, indexName string, pager *Pager, arguments ...interface{}) (totalRows int)

func (*Engine) CachedSearchIDs

func (e *Engine) CachedSearchIDs(entity Entity, indexName string, pager *Pager, arguments ...interface{}) (totalRows int, ids []uint64)

func (*Engine) CachedSearchOne

func (e *Engine) CachedSearchOne(entity Entity, indexName string, arguments ...interface{}) (found bool)

func (*Engine) CachedSearchOneWithReferences

func (e *Engine) CachedSearchOneWithReferences(entity Entity, indexName string, arguments []interface{}, references []string) (found bool)

func (*Engine) CachedSearchWithReferences

func (e *Engine) CachedSearchWithReferences(entities interface{}, indexName string, pager *Pager,
	arguments []interface{}, references []string) (totalRows int)

func (*Engine) ClearByIDs

func (e *Engine) ClearByIDs(entity Entity, ids ...uint64)

func (*Engine) ClearTrackedEntities

func (e *Engine) ClearTrackedEntities()

func (*Engine) DataDog

func (e *Engine) DataDog() DataDog

func (*Engine) EnableDebug

func (e *Engine) EnableDebug()

func (*Engine) EnableLogger

func (e *Engine) EnableLogger(level logApex.Level, handlers ...logApex.Handler)

func (*Engine) EnableQueryDebug

func (e *Engine) EnableQueryDebug(source ...QueryLoggerSource)

func (*Engine) Flush

func (e *Engine) Flush()

func (*Engine) FlushInTransaction

func (e *Engine) FlushInTransaction()

func (*Engine) FlushInTransactionWithCheck

func (e *Engine) FlushInTransactionWithCheck() error

func (*Engine) FlushInTransactionWithLock

func (e *Engine) FlushInTransactionWithLock(lockerPool string, lockName string, ttl time.Duration, waitTimeout time.Duration)

func (*Engine) FlushLazy

func (e *Engine) FlushLazy()

func (*Engine) FlushWithCheck

func (e *Engine) FlushWithCheck() error

func (*Engine) FlushWithFullCheck

func (e *Engine) FlushWithFullCheck() error

func (*Engine) FlushWithLock

func (e *Engine) FlushWithLock(lockerPool string, lockName string, ttl time.Duration, waitTimeout time.Duration)

func (*Engine) ForceMarkToDelete

func (e *Engine) ForceMarkToDelete(entity ...Entity)

func (*Engine) GetAlters

func (e *Engine) GetAlters() (alters []Alter)

func (*Engine) GetClickHouse

func (e *Engine) GetClickHouse(code ...string) *ClickHouse

func (*Engine) GetDirtyBind

func (e *Engine) GetDirtyBind(entity Entity) (bool, map[string]interface{})

func (*Engine) GetElastic

func (e *Engine) GetElastic(code ...string) *Elastic

func (*Engine) GetElasticIndexAlters

func (e *Engine) GetElasticIndexAlters() (alters []ElasticIndexAlter)

func (*Engine) GetLocalCache

func (e *Engine) GetLocalCache(code ...string) *LocalCache

func (*Engine) GetLocker

func (e *Engine) GetLocker(code ...string) *Locker

func (*Engine) GetMysql

func (e *Engine) GetMysql(code ...string) *DB

func (*Engine) GetRabbitMQQueue

func (e *Engine) GetRabbitMQQueue(queueName string) *RabbitMQQueue

func (*Engine) GetRabbitMQRouter

func (e *Engine) GetRabbitMQRouter(queueName string) *RabbitMQRouter

func (*Engine) GetRedis

func (e *Engine) GetRedis(code ...string) *RedisCache

func (*Engine) GetRegistry

func (e *Engine) GetRegistry() ValidatedRegistry

func (*Engine) IsDirty

func (e *Engine) IsDirty(entity Entity) bool

func (*Engine) Load

func (e *Engine) Load(entity Entity, references ...string)

func (*Engine) LoadByID

func (e *Engine) LoadByID(id uint64, entity Entity, references ...string) (found bool)

func (*Engine) LoadByIDs

func (e *Engine) LoadByIDs(ids []uint64, entities interface{}, references ...string) (missing []uint64)

func (*Engine) Loaded

func (e *Engine) Loaded(entity Entity) bool

func (*Engine) Log

func (e *Engine) Log() Log

func (*Engine) MarkDirty

func (e *Engine) MarkDirty(entity Entity, queueCode string, ids ...uint64)

func (*Engine) MarkToDelete

func (e *Engine) MarkToDelete(entity ...Entity)

func (*Engine) Search

func (e *Engine) Search(where *Where, pager *Pager, entities interface{}, references ...string)

func (*Engine) SearchIDs

func (e *Engine) SearchIDs(where *Where, pager *Pager, entity Entity) []uint64

func (*Engine) SearchIDsWithCount

func (e *Engine) SearchIDsWithCount(where *Where, pager *Pager, entity Entity) (results []uint64, totalRows int)

func (*Engine) SearchOne

func (e *Engine) SearchOne(where *Where, entity Entity, references ...string) (found bool)

func (*Engine) SearchWithCount

func (e *Engine) SearchWithCount(where *Where, pager *Pager, entities interface{}, references ...string) (totalRows int)

func (*Engine) SetEntityLogMeta

func (e *Engine) SetEntityLogMeta(key string, value interface{}, entity ...Entity)

func (*Engine) SetLogMetaData

func (e *Engine) SetLogMetaData(key string, value interface{})

func (*Engine) SetOnDuplicateKeyUpdate

func (e *Engine) SetOnDuplicateKeyUpdate(update *Where, entity Entity)

func (*Engine) Track

func (e *Engine) Track(entity ...Entity)

func (*Engine) TrackAndFlush

func (e *Engine) TrackAndFlush(entity ...Entity)

type Entity

type Entity interface {
	GetID() uint64
	SetField(field string, value interface{}) error
	// contains filtered or unexported methods
}

type Enum

type Enum interface {
	GetFields() []string
	GetMapping() map[string]string
	GetDefault() string
	Has(value string) bool
	// contains filtered or unexported methods
}

type EnumModel

type EnumModel struct {
	// contains filtered or unexported fields
}

func (*EnumModel) GetDefault

func (enum *EnumModel) GetDefault() string

func (*EnumModel) GetFields

func (enum *EnumModel) GetFields() []string

func (*EnumModel) GetMapping

func (enum *EnumModel) GetMapping() map[string]string

func (*EnumModel) Has

func (enum *EnumModel) Has(value string) bool

type ExecResult

type ExecResult interface {
	LastInsertId() uint64
	RowsAffected() uint64
}

type ForeignKeyError

type ForeignKeyError struct {
	Message    string
	Constraint string
}

func (*ForeignKeyError) Error

func (err *ForeignKeyError) Error() string

type GetSetProvider

type GetSetProvider func() interface{}

type HTTPAPM

type HTTPAPM interface {
	APM
	SetResponseStatus(status int)
}

type LazyReceiver

type LazyReceiver struct {
	// contains filtered or unexported fields
}

func NewLazyReceiver

func NewLazyReceiver(engine *Engine) *LazyReceiver

func (*LazyReceiver) Digest

func (r *LazyReceiver) Digest()

func (*LazyReceiver) DisableLoop

func (r *LazyReceiver) DisableLoop()

func (*LazyReceiver) Purge

func (r *LazyReceiver) Purge()

func (*LazyReceiver) SetHeartBeat

func (r *LazyReceiver) SetHeartBeat(beat func())

func (*LazyReceiver) SetMaxLoopDuration

func (r *LazyReceiver) SetMaxLoopDuration(duration time.Duration)

type LocalCache

type LocalCache struct {
	// contains filtered or unexported fields
}

func (*LocalCache) Clear

func (c *LocalCache) Clear()

func (*LocalCache) Get

func (c *LocalCache) Get(key string) (value interface{}, ok bool)

func (*LocalCache) GetObjectsCount

func (c *LocalCache) GetObjectsCount() int

func (*LocalCache) GetSet

func (c *LocalCache) GetSet(key string, ttlSeconds int, provider GetSetProvider) interface{}

func (*LocalCache) HMget

func (c *LocalCache) HMget(key string, fields ...string) map[string]interface{}

func (*LocalCache) HMset

func (c *LocalCache) HMset(key string, fields map[string]interface{})

func (*LocalCache) MGet

func (c *LocalCache) MGet(keys ...string) map[string]interface{}

func (*LocalCache) MSet

func (c *LocalCache) MSet(pairs ...interface{})

func (*LocalCache) Remove

func (c *LocalCache) Remove(keys ...string)

func (*LocalCache) Set

func (c *LocalCache) Set(key string, value interface{})

type LocalCacheConfig

type LocalCacheConfig struct {
	// contains filtered or unexported fields
}

type Lock

type Lock struct {
	// contains filtered or unexported fields
}

func (*Lock) Release

func (l *Lock) Release()

func (*Lock) TTL

func (l *Lock) TTL() time.Duration

type Locker

type Locker struct {
	// contains filtered or unexported fields
}

func (*Locker) Obtain

func (l *Locker) Obtain(key string, ttl time.Duration, waitTimeout time.Duration) (lock *Lock, obtained bool)

type Log

type Log interface {
	AddFields(fields apexLog.Fielder)
	Debug(message string, fields apexLog.Fielder)
	Info(message string, fields apexLog.Fielder)
	Warn(message string, fields apexLog.Fielder)
	Error(err interface{}, fields apexLog.Fielder)
	ErrorMessage(message string, fields apexLog.Fielder)
	AddFieldsFromHTTPRequest(r *http.Request, ip string)
	SetHTTPResponseCode(code int)
}

type LogQueueValue

type LogQueueValue struct {
	PoolName  string
	TableName string
	ID        uint64
	LogID     uint64
	Meta      map[string]interface{}
	Before    map[string]interface{}
	Changes   map[string]interface{}
	Updated   time.Time
}

type LogReceiver

type LogReceiver struct {
	Logger func(log *LogQueueValue)
	// contains filtered or unexported fields
}

func NewLogReceiver

func NewLogReceiver(engine *Engine) *LogReceiver

func (*LogReceiver) Digest

func (r *LogReceiver) Digest()

func (*LogReceiver) DisableLoop

func (r *LogReceiver) DisableLoop()

func (*LogReceiver) Purge

func (r *LogReceiver) Purge()

func (*LogReceiver) SetHeartBeat

func (r *LogReceiver) SetHeartBeat(beat func())

type ORM

type ORM struct {
	// contains filtered or unexported fields
}

func (*ORM) GetID

func (orm *ORM) GetID() uint64

func (*ORM) SetField

func (orm *ORM) SetField(field string, value interface{}) error

type Pager

type Pager struct {
	CurrentPage int
	PageSize    int
}

func NewPager

func NewPager(currentPage, pageSize int) *Pager

func (*Pager) GetCurrentPage

func (pager *Pager) GetCurrentPage() int

func (*Pager) GetPageSize

func (pager *Pager) GetPageSize() int

func (*Pager) IncrementPage

func (pager *Pager) IncrementPage()

type PreparedStatement

type PreparedStatement struct {
	// contains filtered or unexported fields
}

func (*PreparedStatement) Exec

func (p *PreparedStatement) Exec(args ...interface{}) sql.Result

type PubSub

type PubSub struct {
	// contains filtered or unexported fields
}

func (*PubSub) Close

func (p *PubSub) Close()

func (*PubSub) Consume

func (p *PubSub) Consume(size int, handler func(items []*redis.Message))

func (*PubSub) DisableLoop

func (p *PubSub) DisableLoop()

func (*PubSub) PUnsubscribe

func (p *PubSub) PUnsubscribe(channels ...string)

func (*PubSub) SetHeartBeat

func (p *PubSub) SetHeartBeat(beat func())

func (*PubSub) SetMaxLoopDuration

func (p *PubSub) SetMaxLoopDuration(duration time.Duration)

func (*PubSub) String

func (p *PubSub) String() string

func (*PubSub) Unsubscribe

func (p *PubSub) Unsubscribe(channels ...string)

type QueryLoggerSource

type QueryLoggerSource int

type RabbitMQConsumer

type RabbitMQConsumer interface {
	Close()
	Consume(handler func(items [][]byte))
	DisableLoop()
	SetHeartBeat(beat func())
	SetMaxLoopDuration(duration time.Duration)
	Purge()
}

type RabbitMQQueue

type RabbitMQQueue struct {
	// contains filtered or unexported fields
}

func (RabbitMQQueue) NewConsumer

func (r RabbitMQQueue) NewConsumer(name string) RabbitMQConsumer

func (*RabbitMQQueue) Publish

func (r *RabbitMQQueue) Publish(body []byte)

type RabbitMQQueueConfig

type RabbitMQQueueConfig struct {
	Name          string
	PrefetchCount int
	Router        string
	Durable       bool
	RouterKeys    []string
	AutoDelete    bool
	TTL           int
}

type RabbitMQRouter

type RabbitMQRouter struct {
	// contains filtered or unexported fields
}

func (RabbitMQRouter) NewConsumer

func (r RabbitMQRouter) NewConsumer(name string) RabbitMQConsumer

func (*RabbitMQRouter) Publish

func (r *RabbitMQRouter) Publish(routerKey string, body []byte)

type RabbitMQRouterConfig

type RabbitMQRouterConfig struct {
	Name    string
	Type    string
	Durable bool
}

type RedisCache

type RedisCache struct {
	// contains filtered or unexported fields
}

func (*RedisCache) Del

func (r *RedisCache) Del(keys ...string)

func (*RedisCache) FlushDB

func (r *RedisCache) FlushDB()

func (*RedisCache) Get

func (r *RedisCache) Get(key string) (value string, has bool)

func (*RedisCache) GetSet

func (r *RedisCache) GetSet(key string, ttlSeconds int, provider GetSetProvider) interface{}

func (*RedisCache) HGetAll

func (r *RedisCache) HGetAll(key string) map[string]string

func (*RedisCache) HMget

func (r *RedisCache) HMget(key string, fields ...string) map[string]interface{}

func (*RedisCache) HMset

func (r *RedisCache) HMset(key string, fields map[string]interface{})

func (*RedisCache) HSet

func (r *RedisCache) HSet(key string, field string, value interface{})

func (*RedisCache) LLen

func (r *RedisCache) LLen(key string) int64

func (*RedisCache) LPush

func (r *RedisCache) LPush(key string, values ...interface{}) int64

func (*RedisCache) LRange

func (r *RedisCache) LRange(key string, start, stop int64) []string

func (*RedisCache) LRem

func (r *RedisCache) LRem(key string, count int64, value interface{})

func (*RedisCache) LSet

func (r *RedisCache) LSet(key string, index int64, value interface{})

func (*RedisCache) Ltrim

func (r *RedisCache) Ltrim(key string, start, stop int64)

func (*RedisCache) MGet

func (r *RedisCache) MGet(keys ...string) map[string]interface{}

func (*RedisCache) MSet

func (r *RedisCache) MSet(pairs ...interface{})

func (*RedisCache) PSubscribe

func (r *RedisCache) PSubscribe(channels ...string) *PubSub

func (*RedisCache) Publish

func (r *RedisCache) Publish(channel string, message interface{})

func (*RedisCache) RPop

func (r *RedisCache) RPop(key string) (value string, found bool)

func (*RedisCache) RPush

func (r *RedisCache) RPush(key string, values ...interface{}) int64

func (*RedisCache) RateLimit

func (r *RedisCache) RateLimit(key string, limit redis_rate.Limit) bool

func (*RedisCache) SAdd

func (r *RedisCache) SAdd(key string, members ...interface{}) int64

func (*RedisCache) SCard

func (r *RedisCache) SCard(key string) int64

func (*RedisCache) SPop

func (r *RedisCache) SPop(key string) (string, bool)

func (*RedisCache) SPopN

func (r *RedisCache) SPopN(key string, max int64) []string

func (*RedisCache) Set

func (r *RedisCache) Set(key string, value interface{}, ttlSeconds int)

func (*RedisCache) Subscribe

func (r *RedisCache) Subscribe(channels ...string) *PubSub

func (*RedisCache) ZAdd

func (r *RedisCache) ZAdd(key string, members ...*redis.Z) int64

func (*RedisCache) ZCard

func (r *RedisCache) ZCard(key string) int64

func (*RedisCache) ZCount

func (r *RedisCache) ZCount(key string, min, max string) int64

func (*RedisCache) ZRangeWithScores

func (r *RedisCache) ZRangeWithScores(key string, start, stop int64) []redis.Z

func (*RedisCache) ZRevRange

func (r *RedisCache) ZRevRange(key string, start, stop int64) []string

func (*RedisCache) ZRevRangeWithScores

func (r *RedisCache) ZRevRangeWithScores(key string, start, stop int64) []redis.Z

func (*RedisCache) ZScore

func (r *RedisCache) ZScore(key, member string) float64

type RedisCacheConfig

type RedisCacheConfig struct {
	// contains filtered or unexported fields
}

type Registry

type Registry struct {
	// contains filtered or unexported fields
}

func InitByYaml

func InitByYaml(yaml map[string]interface{}) (registry *Registry)

func (*Registry) RegisterClickHouse

func (r *Registry) RegisterClickHouse(url string, code ...string)

func (*Registry) RegisterDirtyQueue

func (r *Registry) RegisterDirtyQueue(code string, batchSize int)

func (*Registry) RegisterElastic

func (r *Registry) RegisterElastic(url string, code ...string)

func (*Registry) RegisterElasticIndex

func (r *Registry) RegisterElasticIndex(index ElasticIndexDefinition, serverPool ...string)

func (*Registry) RegisterElasticWithTraceLog

func (r *Registry) RegisterElasticWithTraceLog(url string, code ...string)

func (*Registry) RegisterEntity

func (r *Registry) RegisterEntity(entity ...Entity)

func (*Registry) RegisterEnumMap

func (r *Registry) RegisterEnumMap(code string, val map[string]string, defaultValue string)

func (*Registry) RegisterEnumSlice

func (r *Registry) RegisterEnumSlice(code string, val []string)

func (*Registry) RegisterEnumStruct

func (r *Registry) RegisterEnumStruct(code string, val Enum)

func (*Registry) RegisterLocalCache

func (r *Registry) RegisterLocalCache(size int, code ...string)

func (*Registry) RegisterLocker

func (r *Registry) RegisterLocker(code string, redisCode string)

func (*Registry) RegisterMySQLPool

func (r *Registry) RegisterMySQLPool(dataSourceName string, code ...string)

func (*Registry) RegisterRabbitMQQueue

func (r *Registry) RegisterRabbitMQQueue(config *RabbitMQQueueConfig, serverPool ...string)

func (*Registry) RegisterRabbitMQRouter

func (r *Registry) RegisterRabbitMQRouter(config *RabbitMQRouterConfig, serverPool ...string)

func (*Registry) RegisterRabbitMQServer

func (r *Registry) RegisterRabbitMQServer(address string, code ...string)

func (*Registry) RegisterRedis

func (r *Registry) RegisterRedis(address string, db int, code ...string)

func (*Registry) RegisterRedisRing

func (r *Registry) RegisterRedisRing(addresses []string, db int, code ...string)

func (*Registry) Validate

func (r *Registry) Validate() (ValidatedRegistry, error)

type Rows

type Rows interface {
	Next() bool
	Scan(dest ...interface{})
	Columns() []string
}

type SQLRow

type SQLRow interface {
	Scan(dest ...interface{}) error
}

type SQLRows

type SQLRows interface {
	Next() bool
	Err() error
	Close() error
	Scan(dest ...interface{}) error
	Columns() ([]string, error)
}

type SearchOptions

type SearchOptions struct {
	// contains filtered or unexported fields
}

func (*SearchOptions) AddAggregation

func (p *SearchOptions) AddAggregation(name string, aggregation elastic.Aggregation) *SearchOptions

func (*SearchOptions) AddSort

func (p *SearchOptions) AddSort(field string, ascending bool) *SearchOptions

type TableSchema

type TableSchema interface {
	GetTableName() string
	GetType() reflect.Type
	DropTable(engine *Engine)
	TruncateTable(engine *Engine)
	UpdateSchema(engine *Engine)
	UpdateSchemaAndTruncateTable(engine *Engine)
	GetMysql(engine *Engine) *DB
	GetLocalCache(engine *Engine) (cache *LocalCache, has bool)
	GetRedisCache(engine *Engine) (cache *RedisCache, has bool)
	GetReferences() []string
	GetColumns() []string
	GetUsage(registry ValidatedRegistry) map[reflect.Type][]string
	GetSchemaChanges(engine *Engine) (has bool, alters []Alter)
}

type ValidatedRegistry

type ValidatedRegistry interface {
	CreateEngine() *Engine
	GetTableSchema(entityName string) TableSchema
	GetTableSchemaForEntity(entity Entity) TableSchema
	GetDirtyQueues() map[string]int
	GetSourceRegistry() *Registry
	GetEnum(code string) Enum
	GetEnums() map[string]Enum
	GetEntities() map[string]reflect.Type
}

type Where

type Where struct {
	// contains filtered or unexported fields
}

func NewWhere

func NewWhere(query string, parameters ...interface{}) *Where

func (*Where) Append

func (where *Where) Append(query string, parameters ...interface{})

func (*Where) GetParameters

func (where *Where) GetParameters() []interface{}

func (*Where) String

func (where *Where) String() string

type WorkSpan

type WorkSpan interface {
	Finish()
	SetTag(key string, value interface{})
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL