| package funker |
| |
| import ( |
| "encoding/json" |
| "io/ioutil" |
| "net" |
| "time" |
| ) |
| |
| // Call a Funker function |
| func Call(name string, args interface{}) (interface{}, error) { |
| argsJSON, err := json.Marshal(args) |
| if err != nil { |
| return nil, err |
| } |
| |
| addr, err := net.ResolveTCPAddr("tcp", name+":9999") |
| if err != nil { |
| return nil, err |
| } |
| |
| conn, err := net.DialTCP("tcp", nil, addr) |
| if err != nil { |
| return nil, err |
| } |
| // Keepalive is a workaround for docker/docker#29655 . |
| // The implementation of FIN_WAIT2 seems weird on Swarm-mode. |
| // It seems always refuseing any packet after 60 seconds. |
| // |
| // TODO: remove this workaround if the issue gets resolved on the Docker side |
| if err := conn.SetKeepAlive(true); err != nil { |
| return nil, err |
| } |
| if err := conn.SetKeepAlivePeriod(30 * time.Second); err != nil { |
| return nil, err |
| } |
| if _, err = conn.Write(argsJSON); err != nil { |
| return nil, err |
| } |
| if err = conn.CloseWrite(); err != nil { |
| return nil, err |
| } |
| retJSON, err := ioutil.ReadAll(conn) |
| if err != nil { |
| return nil, err |
| } |
| var ret interface{} |
| err = json.Unmarshal(retJSON, &ret) |
| return ret, err |
| } |