Release to master

This commit is contained in:
Daniel 2020-05-27 15:36:03 +02:00
commit 5df6332635
7 changed files with 395 additions and 220 deletions

292
Gopkg.lock generated
View file

@ -3,46 +3,54 @@
[[projects]]
branch = "master"
digest = "1:6716c9fe6333591128e72848f246fc01dc72240e1e64185d8b4e124e7280b35d"
digest = "1:9cac35beaf0b218e41036e92ec8f664146227a6549a3bd307bb7b223cb40313b"
name = "github.com/AndreasBriese/bbloom"
packages = ["."]
pruneopts = "UT"
revision = "e2d15f34fcf99d5dbb871c820ec73f710fca9815"
pruneopts = ""
revision = "46b345b51c9667fcbaad862a370d73bd7aa802b6"
[[projects]]
digest = "1:e92f5581902c345eb4ceffdcd4a854fb8f73cf436d47d837d1ec98ef1fe0a214"
digest = "1:6146fda730c18186631e91e818d995e759e7cbe27644d6871ccd469f6865c686"
name = "github.com/StackExchange/wmi"
packages = ["."]
pruneopts = "UT"
revision = "5d049714c4a64225c3c79a7cf7d02f7fb5b96338"
version = "1.0.0"
pruneopts = ""
revision = "cbe66965904dbe8a6cd589e2298e5d8b986bd7dd"
version = "1.1.0"
[[projects]]
digest = "1:dbd3a713434b6f32d9459b1e6786ad58cec128470b58555cdc7b3b7314a1706f"
digest = "1:3b186fcaa1c0b374249e76601cd4d5c8c7f0712f8ad419f2e8288c7b9e7ed520"
name = "github.com/aead/serpent"
packages = ["."]
pruneopts = "UT"
pruneopts = ""
revision = "fba169763ea663f7496376e5cdf709e4c7504704"
version = "v0.1"
[[projects]]
branch = "master"
digest = "1:3474fd67b98ac29b6fb7b164306063e9fd380b061a2fb9ba80f6e0a6444102bb"
digest = "1:baf770c4efa1883bb5e444614e85b8028bbad33913aca290a43298f65d9df485"
name = "github.com/bluele/gcache"
packages = ["."]
pruneopts = "UT"
pruneopts = ""
revision = "bc40bd6538339bd4be8cb0b48fc33fdf012ddb6e"
[[projects]]
digest = "1:ffe9824d294da03b391f44e1ae8281281b4afc1bdaa9588c9097785e3af10cec"
digest = "1:d25acc7560ed91f825cb9b01a1e945bb1117cdcaba19077137e2d9ffc9cf6d05"
name = "github.com/cespare/xxhash"
packages = ["."]
pruneopts = ""
revision = "d7df74196a9e781ede915320c11c378c1b2f3a1f"
version = "v2.1.1"
[[projects]]
digest = "1:0deddd908b6b4b768cfc272c16ee61e7088a60f7fe2f06c547bd3d8e1f8b8e77"
name = "github.com/davecgh/go-spew"
packages = ["spew"]
pruneopts = "UT"
pruneopts = ""
revision = "8991bc29aa16c548c550c7ff78260e27b9ab7c73"
version = "v1.1.1"
[[projects]]
digest = "1:6be8582a4f52ba2851d8a039eb9c3a3b90334b2820563d71e97de35580da128e"
digest = "1:238e2deec0c24dca94461b2f72fe05eba40063b653677e60901af56a6fd5148b"
name = "github.com/dgraph-io/badger"
packages = [
".",
@ -50,76 +58,85 @@
"pb",
"skl",
"table",
"trie",
"y",
]
pruneopts = "UT"
revision = "2fa005c9d4bf695277ab5214c1fbce3735b9562a"
version = "v1.6.0"
pruneopts = ""
revision = "8760a5018cd670a5cecc79a7e927ecaf47acc434"
version = "v1.6.1"
[[projects]]
branch = "master"
digest = "1:6e8109ce247a59ab1eeb5330166c12735f6590de99c9647b6162d11518d32c9a"
name = "github.com/dgryski/go-farm"
packages = ["."]
pruneopts = "UT"
revision = "6a90982ecee230ff6cba02d5bd386acc030be9d3"
digest = "1:1d9a7f60f0ff31ba3336a9c1349c212e7076845b537c053a1703a26730145167"
name = "github.com/dgraph-io/ristretto"
packages = ["z"]
pruneopts = ""
revision = "dbc185e050f48c5190a78b4a07829d9c10afca21"
version = "v0.0.2"
[[projects]]
digest = "1:6f9339c912bbdda81302633ad7e99a28dfa5a639c864061f1929510a9a64aa74"
digest = "1:f1a75a8e00244e5ea77ff274baa9559eb877437b240ee7b278f3fc560d9f08bf"
name = "github.com/dustin/go-humanize"
packages = ["."]
pruneopts = "UT"
pruneopts = ""
revision = "9f541cc9db5d55bce703bd99987c9d5cb8eea45e"
version = "v1.0.0"
[[projects]]
digest = "1:440028f55cb322d8cb5b9d5ebec298a00b7d74690a658fe6b1c0c0b44341bfae"
digest = "1:b6581f9180e0f2d5549280d71819ab951db9d511478c87daca95669589d505c0"
name = "github.com/go-ole/go-ole"
packages = [
".",
"oleutil",
]
pruneopts = "UT"
pruneopts = ""
revision = "97b6244175ae18ea6eef668034fd6565847501c9"
version = "v1.2.4"
[[projects]]
digest = "1:573ca21d3669500ff845bdebee890eb7fc7f0f50c59f2132f2a0c6b03d85086a"
name = "github.com/golang/protobuf"
packages = ["proto"]
pruneopts = "UT"
revision = "6c65a5562fc06764971b7c5d05c76c75e84bdbf7"
version = "v1.3.2"
digest = "1:fd608a9f543f30dd5a086b2cdd0bce71b65bca62798ff7ce21348806cdf1412d"
name = "github.com/gofrs/uuid"
packages = ["."]
pruneopts = ""
revision = "abfe1881e60ef34074c1b8d8c63b42565c356ed6"
version = "v3.3.0"
[[projects]]
digest = "1:c3388642e07731a240e14f4bc7207df59cfcc009447c657b9de87fec072d07e3"
digest = "1:02c7a8570f619bdb5620e8f6a16407455c8e63433d8a9e829f618813dc7f89a5"
name = "github.com/golang/protobuf"
packages = ["proto"]
pruneopts = ""
revision = "d04d7b157bb510b1e0c10132224b616ac0e26b17"
version = "v1.4.2"
[[projects]]
digest = "1:20dc576ad8f98fe64777c62f090a9b37dd67c62b23fe42b429c2c41936aa8a9c"
name = "github.com/google/renameio"
packages = ["."]
pruneopts = "UT"
pruneopts = ""
revision = "f0e32980c006571efd537032e5f9cd8c1a92819e"
version = "v0.1.0"
[[projects]]
digest = "1:cbec35fe4d5a4fba369a656a8cd65e244ea2c743007d8f6c1ccb132acf9d1296"
digest = "1:fbab76ba211c99fcd45a481a32530efc229f3510fd94889f361dcaf13ff05fe0"
name = "github.com/gorilla/mux"
packages = ["."]
pruneopts = "UT"
revision = "00bdffe0f3c77e27d2cf6f5c70232a2d3e4d9c15"
version = "v1.7.3"
pruneopts = ""
revision = "75dcda0896e109a2a22c9315bca3bb21b87b2ba5"
version = "v1.7.4"
[[projects]]
digest = "1:7b5c6e2eeaa9ae5907c391a91c132abfd5c9e8a784a341b5625e750c67e6825d"
digest = "1:5122b0b5a933bd0e16b887aa7844933c8a09fb5ba9b5f5651253cb5336c6462a"
name = "github.com/gorilla/websocket"
packages = ["."]
pruneopts = "UT"
revision = "66b9c49e59c6c48f0ffce28c2d8b8a5678502c6d"
version = "v1.4.0"
pruneopts = ""
revision = "b65e62901fc1c0d968042419e74789f6af455eb9"
version = "v1.4.2"
[[projects]]
digest = "1:88e0b0baeb9072f0a4afbcf12dda615fc8be001d1802357538591155998da21b"
digest = "1:2f0c811248aeb64978037b357178b1593372439146bda860cb16f2c80785ea93"
name = "github.com/hashicorp/go-version"
packages = ["."]
pruneopts = "UT"
pruneopts = ""
revision = "ac23dc3fea5d1a983c43f6a0f6e2c13f0195d8bd"
version = "v1.2.0"
@ -127,66 +144,36 @@
digest = "1:870d441fe217b8e689d7949fef6e43efbc787e50f200cb1e70dbca9204a1d6be"
name = "github.com/inconshreveable/mousetrap"
packages = ["."]
pruneopts = "UT"
pruneopts = ""
revision = "76626ae9c91c4f2a10f34cad8ce83ea42c93bb75"
version = "v1.0"
[[projects]]
branch = "master"
digest = "1:7e8b852581596acce37bcb939a05d7d5ff27156045b50057e659e299c16fc1ca"
name = "github.com/mmcloughlin/avo"
packages = [
"attr",
"build",
"buildtags",
"gotypes",
"internal/prnt",
"internal/stack",
"ir",
"operand",
"pass",
"printer",
"reg",
"src",
"x86",
]
pruneopts = "UT"
revision = "bb615f61ce85790a1667efc145c66e917cce1a39"
[[projects]]
digest = "1:cf31692c14422fa27c83a05292eb5cbe0fb2775972e8f1f8446a71549bd8980b"
digest = "1:c45802472e0c06928cd997661f2af610accd85217023b1d5f6331bebce0671d3"
name = "github.com/pkg/errors"
packages = ["."]
pruneopts = "UT"
revision = "ba968bfe8b2f7e042a574c888954fccecfa385b4"
version = "v0.8.1"
pruneopts = ""
revision = "614d223910a179a466c1767a985424175c39b465"
version = "v0.9.1"
[[projects]]
digest = "1:274f67cb6fed9588ea2521ecdac05a6d62a8c51c074c1fccc6a49a40ba80e925"
name = "github.com/satori/go.uuid"
packages = ["."]
pruneopts = "UT"
revision = "f58768cc1a7a7e77a3bd49e98cdd21419399b6a3"
version = "v1.2.0"
[[projects]]
branch = "master"
digest = "1:f1ee4af7c43f206d87f13644636e3710a05e499a084a32ec2cc7d8aa25cef1aa"
digest = "1:90da107a52bdacf25384ae6fc2889df9cf3c956ecde1561825b13ba70a8283b5"
name = "github.com/seehuhn/fortuna"
packages = ["."]
pruneopts = "UT"
revision = "f376bbcd33f446d4431a641aead7851fcbeafa08"
pruneopts = ""
revision = "6f13c9c4f925cf5dd33c070a2f0fbe596385917b"
version = "v1.0.1"
[[projects]]
branch = "master"
digest = "1:c671ecdf2ce51ffaf895169874d074960b3f1297f9bdae49fcb645116d936700"
digest = "1:bf9a02016247817c7ca7dc0d42ee608ffdef20de1474f6d676cfd80a64068a38"
name = "github.com/seehuhn/sha256d"
packages = ["."]
pruneopts = "UT"
revision = "e9f377c596061894b7f9ee69aab61e62c3ccc13e"
pruneopts = ""
revision = "4a65999787a5902349359436a10df5fe59a10a64"
version = "v1.0.0"
[[projects]]
digest = "1:7ebe52387a847d276a9b9e7b379b2e3e4d536843ad840a9c4426a0152e6b3d54"
digest = "1:16f319cf21ddf49f27b3a2093d68316840dc25ec5c2a0a431a4a4fc01ea707e2"
name = "github.com/shirou/gopsutil"
packages = [
"cpu",
@ -196,121 +183,132 @@
"net",
"process",
]
pruneopts = "UT"
revision = "d80c43f9c984a48783daf22f4bd9278006ae483a"
version = "v2.19.7"
pruneopts = ""
revision = "a81cf97fce2300934e6c625b9917103346c26ba3"
version = "v2.20.4"
[[projects]]
branch = "master"
digest = "1:99c6a6dab47067c9b898e8c8b13d130c6ab4ffbcc4b7cc6236c2cd0b1e344f5b"
name = "github.com/shirou/w32"
packages = ["."]
pruneopts = "UT"
revision = "bb4de0191aa41b5507caa14b0650cdbddcd9280b"
[[projects]]
digest = "1:e096613fb7cf34743d49af87d197663cfccd61876e2219853005a57baedfa562"
digest = "1:bff75d4f1a2d2c4b8f4b46ff5ac230b80b5fa49276f615900cba09fe4c97e66e"
name = "github.com/spf13/cobra"
packages = ["."]
pruneopts = "UT"
revision = "f2b07da1e2c38d5f12845a4f607e2e1018cbb1f5"
version = "v0.0.5"
pruneopts = ""
revision = "a684a6d7f5e37385d954dd3b5a14fc6912c6ab9d"
version = "v1.0.0"
[[projects]]
digest = "1:524b71991fc7d9246cc7dc2d9e0886ccb97648091c63e30eef619e6862c955dd"
digest = "1:688428eeb1ca80d92599eb3254bdf91b51d7e232fead3a73844c1f201a281e51"
name = "github.com/spf13/pflag"
packages = ["."]
pruneopts = "UT"
pruneopts = ""
revision = "2e9d26c8c37aae03e3f9d4e90b7116f5accb7cab"
version = "v1.0.5"
[[projects]]
branch = "master"
digest = "1:93d6687fc19da8a35c7352d72117a6acd2072dfb7e9bfd65646227bf2a913b2a"
digest = "1:86e6712cfd4070a2120c03fcec41cfcbbc51813504a74e28d74479edfaf669ee"
name = "github.com/tevino/abool"
packages = ["."]
pruneopts = "UT"
pruneopts = ""
revision = "9b9efcf221b50905aab9bbabd3daed56dc10f339"
[[projects]]
digest = "1:46aea6ffe39c3d95c13640c2515236ed3c5cdffc3c78c6c0ed4edec2caf7a0dc"
digest = "1:029181b60f6ea672544d102f81d7d9508a45a70e17ce8a649535959e0249d56b"
name = "github.com/tidwall/gjson"
packages = ["."]
pruneopts = "UT"
revision = "c5e72cdf74dff23857243dd662c465b810891c21"
version = "v1.3.2"
pruneopts = ""
revision = "f042915ca17de35980544c91ab2c8ceb73b682f2"
version = "v1.6.0"
[[projects]]
digest = "1:8453ddbed197809ee8ca28b06bd04e127bec9912deb4ba451fea7a1eca578328"
digest = "1:72511ec1089fee111c995492d1d390a38ac7ab888aabdb1188985f2a1719c599"
name = "github.com/tidwall/match"
packages = ["."]
pruneopts = "UT"
pruneopts = ""
revision = "33827db735fff6510490d69a8622612558a557ed"
version = "v1.0.1"
[[projects]]
digest = "1:ddfe0a54e5f9b29536a6d7b2defa376f2cb2b6e4234d676d7ff214d5b097cb50"
digest = "1:3d4deb9e8160077721a79fc1b5a6ce27016c98f9f8e631090d5af8f50120ddf0"
name = "github.com/tidwall/pretty"
packages = ["."]
pruneopts = "UT"
revision = "1166b9ac2b65e46a43d8618d30d1554f4652d49b"
version = "v1.0.0"
pruneopts = ""
revision = "b2475501f89994f7ea30b3c94ba86b49079961fe"
version = "v1.0.1"
[[projects]]
digest = "1:b70c951ba6fdeecfbd50dabe95aa5e1b973866ae9abbece46ad60348112214f2"
digest = "1:b749bf81c4c595c1218489d2fa4d90e4a953a5fd11420722a2f57c0c5beecb92"
name = "github.com/tidwall/sjson"
packages = ["."]
pruneopts = "UT"
revision = "25fb082a20e29e83fb7b7ef5f5919166aad1f084"
version = "v1.0.4"
pruneopts = ""
revision = "11cb24d8421de3e1bb5c5efb066a03037150568d"
version = "v1.1.1"
[[projects]]
digest = "1:f2ac2c724fc8214bb7b9dd6d4f5b7a983152051f5133320f228557182263cb94"
digest = "1:2a591e844f6019284ded9f5095e53764c3d69bb8e7d1cf2b318f1b7e25864508"
name = "go.etcd.io/bbolt"
packages = ["."]
pruneopts = "UT"
revision = "a0458a2b35708eef59eb5f620ceb3cd1c01a824d"
version = "v1.3.3"
pruneopts = ""
revision = "68cc10a767ea1c6b9e8dcb9847317ff192d6d974"
version = "v1.3.4"
[[projects]]
branch = "master"
digest = "1:e0efd295a10a5703f556a97b7f90f9b3a02ee5080b26ee5374d100a6131aea68"
digest = "1:305d718b88fcd3b251b910416367de49af1e7944a9a17efabedab5f0ba7745de"
name = "golang.org/x/net"
packages = [
"internal/timeseries",
"trace",
]
pruneopts = "UT"
revision = "74dc4d7220e7acc4e100824340f3e66577424772"
pruneopts = ""
revision = "0ba52f642ac2f9371a88bfdde41f4b4e195a37c0"
[[projects]]
branch = "master"
digest = "1:d52ccbb025caf0a2166e0204ed934567b8d0dfdd23a09d947f1f040708888a0a"
digest = "1:bf837d996e7dfe7b819cbe53c8c9733e93228577f0561e43996b9ef0ea8a68a9"
name = "golang.org/x/sys"
packages = [
"internal/unsafeheader",
"unix",
"windows",
]
pruneopts = "UT"
revision = "fde4db37ae7ad8191b03d30d27f258b5291ae4e3"
pruneopts = ""
revision = "05986578812163b26672dabd9b425240ae2bb0ad"
[[projects]]
branch = "master"
digest = "1:b3e64b43fe77039813b4f33100e4ef2e17960309f3c6c9ab120f5c55de747992"
name = "golang.org/x/tools"
digest = "1:f3bbd8ea54cde834a67fc50f27cbdf35eb950225953fb304891be068ba82d163"
name = "google.golang.org/protobuf"
packages = [
"go/ast/astutil",
"go/gcexportdata",
"go/internal/gcimporter",
"go/internal/packagesdriver",
"go/packages",
"go/types/typeutil",
"internal/fastwalk",
"internal/gopathwalk",
"internal/semver",
"encoding/prototext",
"encoding/protowire",
"internal/descfmt",
"internal/descopts",
"internal/detrand",
"internal/encoding/defval",
"internal/encoding/messageset",
"internal/encoding/tag",
"internal/encoding/text",
"internal/errors",
"internal/fieldnum",
"internal/fieldsort",
"internal/filedesc",
"internal/filetype",
"internal/flags",
"internal/genname",
"internal/impl",
"internal/mapsort",
"internal/pragma",
"internal/set",
"internal/strs",
"internal/version",
"proto",
"reflect/protoreflect",
"reflect/protoregistry",
"runtime/protoiface",
"runtime/protoimpl",
]
pruneopts = "UT"
revision = "caa95bb40b630f80d344d1f710f7e39be971d3e8"
pruneopts = ""
revision = "d165be301fb1e13390ad453281ded24385fd8ebc"
version = "v1.23.0"
[solve-meta]
analyzer-name = "dep"
@ -320,11 +318,11 @@
"github.com/bluele/gcache",
"github.com/davecgh/go-spew/spew",
"github.com/dgraph-io/badger",
"github.com/gofrs/uuid",
"github.com/google/renameio",
"github.com/gorilla/mux",
"github.com/gorilla/websocket",
"github.com/hashicorp/go-version",
"github.com/satori/go.uuid",
"github.com/seehuhn/fortuna",
"github.com/shirou/gopsutil/host",
"github.com/spf13/cobra",

View file

@ -23,72 +23,3 @@
# non-go = false
# go-tests = true
# unused-packages = true
[[constraint]]
name = "github.com/aead/serpent"
version = "0.1.0"
[[constraint]]
branch = "master"
name = "github.com/bluele/gcache"
[[constraint]]
name = "github.com/davecgh/go-spew"
version = "1.1.1"
[[constraint]]
name = "github.com/dgraph-io/badger"
version = "1.5.4"
[[constraint]]
name = "github.com/google/renameio"
version = "0.1.0"
[[constraint]]
name = "github.com/gorilla/mux"
version = "1.7.3"
[[constraint]]
name = "github.com/gorilla/websocket"
version = "1.4.0"
[[constraint]]
branch = "master"
name = "github.com/seehuhn/fortuna"
[[constraint]]
branch = "master"
name = "github.com/tevino/abool"
[[constraint]]
name = "github.com/tidwall/gjson"
version = "1.2.1"
[[constraint]]
name = "github.com/tidwall/sjson"
version = "1.0.4"
[[constraint]]
name = "go.etcd.io/bbolt"
version = "1.3.2"
[[constraint]]
branch = "master"
name = "golang.org/x/sys"
[prune]
go-tests = true
unused-packages = true
[[constraint]]
name = "github.com/satori/go.uuid"
version = "1.2.0"
[[constraint]]
name = "github.com/shirou/gopsutil"
version = "2.19.6"
[[constraint]]
name = "github.com/hashicorp/go-version"
version = "1.2.0"

View file

@ -8,8 +8,7 @@ import (
"github.com/safing/portbase/database"
"github.com/safing/portbase/database/record"
"github.com/safing/portbase/log"
uuid "github.com/satori/go.uuid"
"github.com/safing/portbase/utils"
)
// Notification types
@ -96,7 +95,7 @@ func notify(nType uint8, id string, msg string, actions ...Action) *Notification
}
if id == "" {
id = uuid.NewV4().String()
id = utils.DerivedInstanceUUID(msg).String()
}
n := Notification{
@ -121,7 +120,7 @@ func (n *Notification) Save() *Notification {
n.Created = time.Now().Unix()
}
if n.GUID == "" {
n.GUID = uuid.NewV4().String()
n.GUID = utils.RandomUUID(n.ID).String()
}
// make ack notification if there are no defined actions

78
utils/onceagain.go Normal file
View file

@ -0,0 +1,78 @@
package utils
// This file is forked from https://github.com/golang/go/blob/bc593eac2dc63d979a575eccb16c7369a5ff81e0/src/sync/once.go.
import (
"sync"
"sync/atomic"
)
// OnceAgain is an object that will perform only one action "in flight". It's basically the same as sync.Once, but is automatically reused when the function was executed and everyone who waited has left.
type OnceAgain struct {
// done indicates whether the action has been performed.
// It is first in the struct because it is used in the hot path.
// The hot path is inlined at every call site.
// Placing done first allows more compact instructions on some architectures (amd64/x86),
// and fewer instructions (to calculate offset) on other architectures.
done uint32
// Number of waiters waiting for the function to finish. The last waiter resets done.
waiters int32
m sync.Mutex
}
// Do calls the function f if and only if Do is being called for the
// first time for this instance of Once. In other words, given
// var once Once
// if once.Do(f) is called multiple times, only the first call will invoke f,
// even if f has a different value in each invocation. A new instance of
// Once is required for each function to execute.
//
// Do is intended for initialization that must be run exactly once. Since f
// is niladic, it may be necessary to use a function literal to capture the
// arguments to a function to be invoked by Do:
// config.once.Do(func() { config.init(filename) })
//
// Because no call to Do returns until the one call to f returns, if f causes
// Do to be called, it will deadlock.
//
// If f panics, Do considers it to have returned; future calls of Do return
// without calling f.
//
func (o *OnceAgain) Do(f func()) {
// Note: Here is an incorrect implementation of Do:
//
// if atomic.CompareAndSwapUint32(&o.done, 0, 1) {
// f()
// }
//
// Do guarantees that when it returns, f has finished.
// This implementation would not implement that guarantee:
// given two simultaneous calls, the winner of the cas would
// call f, and the second would return immediately, without
// waiting for the first's call to f to complete.
// This is why the slow path falls back to a mutex, and why
// the atomic.StoreUint32 must be delayed until after f returns.
if atomic.LoadUint32(&o.done) == 0 {
// Outlined slow-path to allow inlining of the fast-path.
o.doSlow(f)
}
}
func (o *OnceAgain) doSlow(f func()) {
atomic.AddInt32(&o.waiters, 1)
defer func() {
if atomic.AddInt32(&o.waiters, -1) == 0 {
atomic.StoreUint32(&o.done, 0) // reset
}
}()
o.m.Lock()
defer o.m.Unlock()
if o.done == 0 {
defer atomic.StoreUint32(&o.done, 1)
f()
}
}

55
utils/onceagain_test.go Normal file
View file

@ -0,0 +1,55 @@
package utils
import (
"sync"
"sync/atomic"
"testing"
"time"
"github.com/tevino/abool"
)
func TestOnceAgain(t *testing.T) {
oa := OnceAgain{}
executed := abool.New()
var testWg sync.WaitGroup
// basic
for i := 0; i < 10; i++ {
testWg.Add(100)
for i := 0; i < 100; i++ {
go func() {
oa.Do(func() {
if !executed.SetToIf(false, true) {
t.Errorf("concurrent execution!")
}
time.Sleep(10 * time.Millisecond)
})
testWg.Done()
}()
}
testWg.Wait()
executed.UnSet() // reset check
}
// streaming
var execs uint32
testWg.Add(100)
for i := 0; i < 100; i++ {
go func() {
oa.Do(func() {
atomic.AddUint32(&execs, 1)
time.Sleep(10 * time.Millisecond)
})
testWg.Done()
}()
time.Sleep(1 * time.Millisecond)
}
testWg.Wait()
if execs >= 20 {
t.Errorf("unexpected high exec count: %d", execs)
}
}

45
utils/uuid.go Normal file
View file

@ -0,0 +1,45 @@
package utils
import (
"encoding/binary"
"time"
"github.com/gofrs/uuid"
)
var (
constantUUID = uuid.Must(uuid.FromString("e8dba9f7-21e2-4c82-96cb-6586922c6422"))
instanceUUID = RandomUUID("instance")
)
// RandomUUID returns a new random UUID with optionally provided ns
func RandomUUID(ns string) uuid.UUID {
randUUID, err := uuid.NewV4()
switch {
case err != nil:
// fallback
// should practically never happen
return uuid.NewV5(uuidFromTime(), ns)
case ns != "":
// mix ns into the UUID
return uuid.NewV5(randUUID, ns)
default:
return randUUID
}
}
// DerivedUUID returns a new UUID that is derived from the input only, and therefore is always reproducible.
func DerivedUUID(input string) uuid.UUID {
return uuid.NewV5(constantUUID, input)
}
// DerivedInstanceUUID returns a new UUID that is derived from the input, but is unique per instance (execution) and therefore is only reproducible with the same process.
func DerivedInstanceUUID(input string) uuid.UUID {
return uuid.NewV5(instanceUUID, input)
}
func uuidFromTime() uuid.UUID {
var timeUUID uuid.UUID
binary.LittleEndian.PutUint64(timeUUID[:], uint64(time.Now().UnixNano()))
return timeUUID
}

69
utils/uuid_test.go Normal file
View file

@ -0,0 +1,69 @@
package utils
import (
"testing"
"time"
"github.com/gofrs/uuid"
)
func TestUUID(t *testing.T) {
// check randomness
a := RandomUUID("")
a2 := RandomUUID("")
if a.String() == a2.String() {
t.Error("should not match")
}
// check with input
b := RandomUUID("b")
b2 := RandomUUID("b")
if b.String() == b2.String() {
t.Error("should not match")
}
// check with long input
c := RandomUUID("TG8UkxS+4rVrDxHtDAaNab1CBpygzmX1g5mJA37jbQ5q2uE4rVrDxHtDAaNab1CBpygzmX1g5mJA37jbQ5q2uE")
c2 := RandomUUID("TG8UkxS+4rVrDxHtDAaNab1CBpygzmX1g5mJA37jbQ5q2uE4rVrDxHtDAaNab1CBpygzmX1g5mJA37jbQ5q2uE")
if c.String() == c2.String() {
t.Error("should not match")
}
// check for nanosecond precision
d := uuidFromTime()
time.Sleep(2 * time.Nanosecond)
d2 := uuidFromTime()
if d.String() == d2.String() {
t.Error("should not match")
}
// check mixing
timeUUID := uuidFromTime()
e := uuid.NewV5(timeUUID, "e")
e2 := uuid.NewV5(timeUUID, "e2")
if e.String() == e2.String() {
t.Error("should not match")
}
// check deriving
f := DerivedUUID("f")
f2 := DerivedUUID("f")
f3 := DerivedUUID("f3")
if f.String() != f2.String() {
t.Error("should match")
}
if f.String() == f3.String() {
t.Error("should not match")
}
// check instance deriving
g := DerivedInstanceUUID("g")
g2 := DerivedInstanceUUID("g")
g3 := DerivedInstanceUUID("g3")
if g.String() != g2.String() {
t.Error("should match")
}
if g.String() == g3.String() {
t.Error("should not match")
}
}