call.go 1.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950
  1. package funker
  2. import (
  3. "encoding/json"
  4. "io/ioutil"
  5. "net"
  6. "time"
  7. )
  8. // Call a Funker function
  9. func Call(name string, args interface{}) (interface{}, error) {
  10. argsJSON, err := json.Marshal(args)
  11. if err != nil {
  12. return nil, err
  13. }
  14. addr, err := net.ResolveTCPAddr("tcp", name+":9999")
  15. if err != nil {
  16. return nil, err
  17. }
  18. conn, err := net.DialTCP("tcp", nil, addr)
  19. if err != nil {
  20. return nil, err
  21. }
  22. // Keepalive is a workaround for docker/docker#29655 .
  23. // The implementation of FIN_WAIT2 seems weird on Swarm-mode.
  24. // It seems always refuseing any packet after 60 seconds.
  25. //
  26. // TODO: remove this workaround if the issue gets resolved on the Docker side
  27. if err := conn.SetKeepAlive(true); err != nil {
  28. return nil, err
  29. }
  30. if err := conn.SetKeepAlivePeriod(30 * time.Second); err != nil {
  31. return nil, err
  32. }
  33. if _, err = conn.Write(argsJSON); err != nil {
  34. return nil, err
  35. }
  36. if err = conn.CloseWrite(); err != nil {
  37. return nil, err
  38. }
  39. retJSON, err := ioutil.ReadAll(conn)
  40. if err != nil {
  41. return nil, err
  42. }
  43. var ret interface{}
  44. err = json.Unmarshal(retJSON, &ret)
  45. return ret, err
  46. }