github.com/unigraph-dev/dgraph@v1.1.1-0.20200923154953-8b52b426f765/contrib/integration/bigdata/main.go (about) 1 /* 2 * Copyright 2018 Dgraph Labs, Inc. and Contributors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package main 18 19 import ( 20 "context" 21 "encoding/json" 22 "flag" 23 "fmt" 24 "math/rand" 25 "net/url" 26 "os" 27 "strings" 28 "sync/atomic" 29 "time" 30 31 "github.com/dgraph-io/dgo" 32 "github.com/dgraph-io/dgo/protos/api" 33 "github.com/dgraph-io/dgo/x" 34 "google.golang.org/grpc" 35 ) 36 37 var addrs = flag.String("addrs", "", "comma separated dgraph addresses") 38 var mode = flag.String("mode", "", "mode to run in ('mutate' or 'query')") 39 var conc = flag.Int("j", 1, "number of operations to run in parallel") 40 41 func init() { 42 rand.Seed(time.Now().Unix()) 43 } 44 45 var ctx = context.Background() 46 47 func main() { 48 flag.Parse() 49 c := makeClient() 50 51 // Install the schema automatically on the first run. This allows the same 52 // command to be used when running this program for the first and 53 // subsequent times. We guess if it's the first run based on the number of 54 // schema items. 55 resp, err := c.NewTxn().Query(ctx, "schema {}") 56 x.Check(err) 57 if len(resp.Json) < 5 { 58 // Run each schema alter separately so that there is an even 59 // distribution among all groups. 60 for _, s := range schema() { 61 x.Check(c.Alter(ctx, &api.Operation{ 62 Schema: s, 63 })) 64 } 65 x.Check2(c.NewTxn().Mutate(ctx, &api.Mutation{ 66 CommitNow: true, 67 SetNquads: []byte(initialData()), 68 })) 69 } 70 71 switch *mode { 72 case "mutate": 73 var errCount int64 74 var mutateCount int64 75 for i := 0; i < *conc; i++ { 76 go func() { 77 for { 78 err := mutate(c) 79 if err == nil { 80 atomic.AddInt64(&mutateCount, 1) 81 } else { 82 atomic.AddInt64(&errCount, 1) 83 } 84 } 85 }() 86 } 87 for { 88 time.Sleep(time.Second) 89 fmt.Printf("Status: success_mutations=%d errors=%d\n", 90 atomic.LoadInt64(&mutateCount), atomic.LoadInt64(&errCount)) 91 } 92 case "query": 93 var errCount int64 94 var queryCount int64 95 for i := 0; i < *conc; i++ { 96 go func() { 97 for { 98 err := showNode(c) 99 if err == nil { 100 atomic.AddInt64(&queryCount, 1) 101 } else { 102 atomic.AddInt64(&errCount, 1) 103 } 104 } 105 }() 106 } 107 for { 108 time.Sleep(time.Second) 109 fmt.Printf("Status: success_queries=%d errors=%d\n", 110 atomic.LoadInt64(&queryCount), atomic.LoadInt64(&errCount)) 111 } 112 default: 113 fmt.Printf("unknown mode: %q\n", *mode) 114 os.Exit(1) 115 } 116 } 117 118 func schema() []string { 119 s := []string{"xid: string @index(exact) .\n"} 120 for char := 'a'; char <= 'z'; char++ { 121 s = append(s, fmt.Sprintf("count_%c: int .\n", char)) 122 } 123 for char := 'a'; char <= 'z'; char++ { 124 s = append(s, fmt.Sprintf("attr_%c: string .\n", char)) 125 } 126 return s 127 } 128 129 func initialData() string { 130 rdfs := "_:root <xid> \"root\" .\n" 131 for char := 'a'; char <= 'z'; char++ { 132 rdfs += fmt.Sprintf("_:root <count_%c> \"0\" .\n", char) 133 } 134 return rdfs 135 } 136 137 func makeClient() *dgo.Dgraph { 138 var dgcs []api.DgraphClient 139 for _, addr := range strings.Split(*addrs, ",") { 140 c, err := grpc.Dial(addr, grpc.WithInsecure()) 141 x.Check(err) 142 dgcs = append(dgcs, api.NewDgraphClient(c)) 143 } 144 return dgo.NewDgraphClient(dgcs...) 145 } 146 147 type runner struct { 148 txn *dgo.Txn 149 } 150 151 func mutate(c *dgo.Dgraph) error { 152 r := &runner{ 153 txn: c.NewTxn(), 154 } 155 defer func() { _ = r.txn.Discard(ctx) }() 156 157 char := 'a' + rune(rand.Intn(26)) 158 159 var result struct { 160 Q []struct { 161 Uid *string 162 Count *int 163 } 164 } 165 if err := r.query(&result, ` 166 { 167 q(func: eq(xid, "root")) { 168 uid 169 count: count_%c 170 } 171 } 172 `, char); err != nil { 173 return err 174 } 175 176 x.AssertTrue(len(result.Q) > 0 && result.Q[0].Count != nil && result.Q[0].Uid != nil) 177 178 if _, err := r.txn.Mutate(ctx, &api.Mutation{ 179 SetNquads: []byte(fmt.Sprintf("<%s> <count_%c> \"%d\" .\n", 180 *result.Q[0].Uid, char, *result.Q[0].Count+1)), 181 }); err != nil { 182 return err 183 } 184 185 rdfs := fmt.Sprintf("_:node <xid> \"%c_%d\" .\n", char, *result.Q[0].Count) 186 for char := 'a'; char <= 'z'; char++ { 187 if rand.Float64() < 0.9 { 188 continue 189 } 190 payload := make([]byte, 16+rand.Intn(16)) 191 rand.Read(payload) 192 rdfs += fmt.Sprintf("_:node <attr_%c> \"%s\" .\n", char, url.QueryEscape(string(payload))) 193 } 194 if _, err := r.txn.Mutate(ctx, &api.Mutation{ 195 SetNquads: []byte(rdfs), 196 }); err != nil { 197 return err 198 } 199 200 return r.txn.Commit(ctx) 201 } 202 203 func showNode(c *dgo.Dgraph) error { 204 r := &runner{ 205 txn: c.NewTxn(), 206 } 207 defer func() { _ = r.txn.Discard(ctx) }() 208 209 char := 'a' + rune(rand.Intn(26)) 210 var result struct { 211 Q []struct { 212 Count *int 213 } 214 } 215 216 q := fmt.Sprintf(` 217 { 218 q(func: eq(xid, "root")) { 219 uid 220 count: count_%c 221 } 222 } 223 `, char) 224 resp, err := r.txn.Query(ctx, q) 225 if err != nil { 226 return err 227 } 228 if err := json.Unmarshal(resp.Json, &result); err != nil { 229 return err 230 } 231 x.AssertTruef(len(result.Q) > 0 && result.Q[0].Count != nil, "%v %+v", string(resp.Json), result) 232 233 var m map[string]interface{} 234 return r.query(&m, ` 235 { 236 q(func: eq(xid, "%c_%d")) { 237 expand(_all_) 238 } 239 } 240 `, char, rand.Intn(*result.Q[0].Count)) 241 } 242 243 func (r *runner) query(out interface{}, q string, args ...interface{}) error { 244 q = fmt.Sprintf(q, args...) 245 resp, err := r.txn.Query(ctx, q) 246 if err != nil { 247 return err 248 } 249 return json.Unmarshal(resp.Json, out) 250 }