<commit_before>package gremgo

import (
	"io/ioutil"
	"sync"
)

// Client is a container for the gremgo client.
type Client struct {
	conn             dialer
	requests         chan []byte
	responses        chan []byte
	results          map[string][]interface{}
	responseNotifyer map[string]chan int // responseNotifyer notifies the requester that a response has arrived for the request
	respMutex        *sync.Mutex
}

// NewDialer returns a WebSocket dialer to use when connecting to Gremlin Server
func NewDialer(host string) (dialer *Ws) {
	dialer = new(Ws)
	dialer.host = "ws://" + host
	return dialer
}

func newClient() (c Client) {
	c.requests = make(chan []byte, 3)  // c.requests takes any request and delivers it to the WriteWorker for dispatch to Gremlin Server
	c.responses = make(chan []byte, 3) // c.responses takes raw responses from ReadWorker and delivers it for sorting to handelResponse
	c.results = make(map[string][]interface{})
	c.responseNotifyer = make(map[string]chan int)
	c.respMutex = &sync.Mutex{} // c.mutex ensures that sorting is thread safe
	return
}

// Dial returns a gremgo client for interaction with the Gremlin Server specified in the host IP.
func Dial(conn dialer) (c Client, err error) {

	c = newClient()
	c.conn = conn

	// Connects to Gremlin Server
	err = conn.connect()
	if err != nil {
		return
	}

	go c.writeWorker()
	go c.readWorker()

	return
}

func (c *Client) executeRequest(query string, bindings map[string]string) (resp interface{}, err error) {
	req, id := prepareRequest(query, bindings)
	msg, err := packageRequest(req)
	if err != nil {
		return // TODO: Fix error handling
	}
	c.responseNotifyer[id] = make(chan int, 1)
	c.dispatchRequest(msg)
	resp = c.retrieveResponse(id)
	return
}

// Execute formats a raw Gremlin query, sends it to Gremlin Server, and returns the result.
func (c *Client) Execute(query string, bindings map[string]string) (resp interface{}, err error) {
	resp, err = c.executeRequest(query, bindings)
	return
}

// ExecuteFile takes a file path to a Gremlin script, sends it to Gremlin Server, and returns the result.
func (c *Client) ExecuteFile(path string, bindings map[string]string) (resp interface{}, err error) {
	d, err := ioutil.ReadFile(path) // Read script from file
	if err != nil {
		return
	}
	query := string(d)
	resp, err = c.executeRequest(query, bindings)
	return
}
<commit_msg>Added some logging for error events. Added close method to Client so that hte underlying socket connection can be closed if needed.<commit_after>package gremgo

import (
	"io/ioutil"
	"log"
	"sync"
)

// Client is a container for the gremgo client.
type Client struct {
	conn             dialer
	requests         chan []byte
	responses        chan []byte
	results          map[string][]interface{}
	responseNotifyer map[string]chan int // responseNotifyer notifies the requester that a response has arrived for the request
	respMutex        *sync.Mutex
	Errored          bool
}

// NewDialer returns a WebSocket dialer to use when connecting to Gremlin Server
func NewDialer(host string) (dialer *Ws) {
	dialer = new(Ws)
	dialer.host = "ws://" + host
	return dialer
}

func newClient() (c Client) {
	c.requests = make(chan []byte, 3)  // c.requests takes any request and delivers it to the WriteWorker for dispatch to Gremlin Server
	c.responses = make(chan []byte, 3) // c.responses takes raw responses from ReadWorker and delivers it for sorting to handelResponse
	c.results = make(map[string][]interface{})
	c.responseNotifyer = make(map[string]chan int)
	c.respMutex = &sync.Mutex{} // c.mutex ensures that sorting is thread safe
	return
}

// Dial returns a gremgo client for interaction with the Gremlin Server specified in the host IP.
func Dial(conn dialer) (c Client, err error) {

	c = newClient()
	c.conn = conn

	// Connects to Gremlin Server
	err = conn.connect()
	if err != nil {
		return
	}

	go c.writeWorker()
	go c.readWorker()

	return
}

func (c *Client) executeRequest(query string, bindings map[string]string) (resp interface{}, err error) {
	req, id := prepareRequest(query, bindings)
	msg, err := packageRequest(req)
	if err != nil {
		log.Println(err)
		return
	}
	c.responseNotifyer[id] = make(chan int, 1)
	c.dispatchRequest(msg)
	resp = c.retrieveResponse(id)
	return
}

// Execute formats a raw Gremlin query, sends it to Gremlin Server, and returns the result.
func (c *Client) Execute(query string, bindings map[string]string) (resp interface{}, err error) {
	resp, err = c.executeRequest(query, bindings)
	return
}

// ExecuteFile takes a file path to a Gremlin script, sends it to Gremlin Server, and returns the result.
func (c *Client) ExecuteFile(path string, bindings map[string]string) (resp interface{}, err error) {
	d, err := ioutil.ReadFile(path) // Read script from file
	if err != nil {
		log.Println(err)
		return
	}
	query := string(d)
	resp, err = c.executeRequest(query, bindings)
	return
}

// Close closes the underlying connection and marks the client as closed.
func (c *Client) Close() {
	if c.conn != nil {
		c.conn.close()
	}
}

{'fraction_non_alphanumeric': 0.10308056872037914, 'fraction_numerical': 0.001184834123222749, 'mean_word_length': 3.819219790675547, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2385761', 'n_tokens_mistral': 1654, 'n_tokens_neox': 1585, 'n_words': 593}