Beispiel #1
0
func MaterializeUnion(name string, field ...string) Reflex {
	reflex, eye := plumb.NewEye(append(field, name)...)
	go func() {
		conj := New()
		for {
			dvalve, dvalue := eye.See()
			if dvalve == name { // conjunction updated
				y := make(chan struct{})   // block and
				for _, f_ := range field { // send updated conjunction to all field valves
					f := f_
					go func() {
						eye.Show(f, dvalue.(Circuit).At(f))
						y <- struct{}{}
					}()
				}
				for _ = range field {
					<-y
				}
			} else { // field updated
				conj.Abandon(dvalve).Grow(dvalve, dvalue)
				if conj.Len() == len(field) {
					eye.Show(name, conj)
				}
			}
		}
	}()
	return reflex
}
Beispiel #2
0
func (Ticker) Materialize() be.Reflex {
	reflex, eye := plumb.NewEye("Tick", "Duration")
	go func() {
		for {
			valve, value := eye.See()
			switch valve {
			case "Duration":
				dur := time.Duration(plumb.AsInt(value))
				if dur <= 0 {
					panic(4)
				}
				abr := make(chan struct{})
				go func() {
					start := time.Now()
					tkr := time.NewTicker(dur)
					defer tkr.Stop()
					for {
						select {
						case <-abr:
							return
						case t := <-tkr.C:
							eye.Show("Tick", int(t.Sub(start)))
						}
					}
				}()
			}
		}
	}()
	return reflex
}
Beispiel #3
0
func MaterializeSubscription(kind string) be.Reflex {
	reflex, eye := plumb.NewEye("Server", "_")
	go func() {
		var server string
		for {
			valve, value := eye.See()
			?? // use containerlike spawn param with server and name!!
			if valve != "Server" || server != "" {
				continue
			}
			server = value.(string)
			go func() {
				id := ChooseID()
				anchor := program.Client.Walk(
					??
					[]string{
						server, 
						"escher", 
						program.Name, 
						"circuit." + kind, 
						id,
					},
				)
				var ss client.Subscription
				var err error
				switch kind {
				case "Joining":
					ss, err = anchor.MakeOnJoin()
				case "Leaving":
					ss, err = anchor.MakeOnLeave()
				default:
					panic(2)
				}
				if err != nil {
					panic("plugging")
				}
				defer anchor.Scrub()
				for {
					v, ok := ss.Consume()
					if !ok {
						panic("subscription should not be closing ever")
					}
					eye.Show("_", v)
				}
			}()
		}
	}()
	return reflex
}
Beispiel #4
0
// Fix creates a gate that waits until all fix valves are set and
// then outputs a singular conjunction of all values.
func MaterializeFix(fwd string, fix ...string) be.Reflex {
	reflex, eye := plumb.NewEye(append(fix, fwd)...)
	go func() {
		conj := New()
		for {
			dvalve, dvalue := eye.See()
			if dvalve == fwd { // conjunction updated
				continue // ignore upstream updates
			} else { // field updated
				conj.Abandon(dvalve).Grow(dvalve, dvalue)
				if conj.Len() == len(fix) {
					eye.Show(fwd, conj)
					eye.Drain() // As soon as the conjunction is output, this gate is done.
				}
			}
		}
	}()
	return reflex
}
Beispiel #5
0
func (Delay) Materialize() be.Reflex {
	reflex, eye := plumb.NewEye("X", "Y", "Duration")
	go func() {
		ds := make(chan time.Duration, 2)
		dur := ds
		xy, yx := make(chan interface{}, 1), make(chan interface{}, 1)
		go func() {
			d := <-dur
			for {
				v := <-xy
				time.Sleep(d)
				eye.Show("Y", v)
			}
		}()
		go func() {
			d := <-dur
			for {
				v := <-yx
				time.Sleep(d)
				eye.Show("X", v)
			}
		}()
		for {
			valve, value := eye.See()
			switch valve {
			case "X":
				xy <- value
			case "Y":
				yx <- value
			case "Duration":
				if ds == nil {
					break
				}
				d := time.Duration(value.(int))
				ds <- d
				ds <- d
				close(ds)
				ds = nil
			}
		}
	}()
	return reflex
}
Beispiel #6
0
//	File string
//	Put {Key []byte, Value []byte}
//	Query {Name interface{}, Start []byte, Limit []byte}
//	Result {Name interface{}, Result Image}
func (File) Materialize() be.Reflex {
	reflex, eye := plumb.NewEye("File", "Put", "Query", "Result")
	go func() { // dispatch
		var err error
		var db *leveldb.DB
		connected, put, query := make(chan struct{}), make(chan Image, 5), make(chan Image, 5)
		go func() { // Put loop
			<-connected // wait for db connection
			for {
				p := <-put
				if err := db.Put(p[see.Name("Key")].([]byte), p[see.Name("Value")].([]byte), nil); err != nil {
					panic(err)
				}
			}
		}()
		go func() { // Query loop
			<-connected // wait for db connection
			for {
				q := <-query
				iter := db.NewIterator(
					&util.Range{
						Start: q[see.Name("Start")].([]byte),
						Limit: q[see.Name("Limit")].([]byte),
					},
					nil,
				)
				slice := Make()
				if iter.First() {
					for i := 0; ; i++ {
						if err := iter.Error(); err != nil {
							panic(err)
						}
						slice.Grow(
							see.Number(i),
							Image{
								see.Name("Key"):   iter.Key(),
								see.Name("Value"): iter.Value(),
							},
						)
						if !iter.Next() {
							break
						}
					}
				}
				eye.Show("Result", Make().Grow(see.Name("Name"), q[see.Name("Name")]).Grow(see.Name("Slice"), slice))
			}
		}()
		for {
			valve, value := eye.See()
			switch valve {
			case "File":
				if db, err = leveldb.OpenFile(value.(string), nil); err != nil {
					panic(err)
				}
				close(connected)
			case "Put":
				put <- value.(Image)
			case "Query":
				query <- value.(Image)
			}
		}
	}()
	return reflex
}