mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-05-17 15:09:59 +00:00
* implements futures functions and GRPC functions on new branch * lint and test fixes * Fix uneven split pnl. Adds collateral weight test. docs. New clear func * Test protection if someone has zero collateral * Uses string instead of double for accuracy * Fixes old code panic * context, match, docs * Addresses Shazniterinos, var names, expanded tests * Returns subaccount name, provides USD values when offlinecalc * Fixes oopsie * Fixes cool bug which allowed made up subaccount results * Subaccount override on FTX, subaccount results for collateral * Strenghten collateral account info checks. Improve FTX test * English is my first language * Fixes oopsies * Fixes for unrealised PNL & collateral rendering * Fixes lint and tests * Shaznit fixes * Secret Shaznit * Updates account information across wrappers to include more fields * Updates online collateral calculations. Updates RPC data * Accurately calculates collateral offline and online minus testing * Tests and lint chocolate * Simplifies accountinfo results * Fixes shaznits * Adds new func * Increases collateral accuracy again again again x 200 * Increases accuracy of collateral rendering * Fixes minor merge/test issues * Linterino * Fixes ws test. Improves collateral calculations and rendering * Make it prettier * Removes the lock I put on 👀 * Adds `additional_collateral_used` field, renders orig currency * Fixes unrelated test * Fix test * Correctly calculate spot margin borrow collateral * Address fun lint surprise See https://github.com/golangci/golangci-lint/issues/741#issuecomment-1017014331 * Strange lint fixing x2 * Continued lint journey * Nolint the nolint to not lint the lint * Adds two new fields to response * More linting issues arising * fIX3s_c4s|NG * Fixes command flags' incorrect numbering * FairMarket = Won
92 lines
2.0 KiB
Go
92 lines
2.0 KiB
Go
package log
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
)
|
|
|
|
var (
|
|
errWriterAlreadyLoaded = errors.New("io.Writer already loaded")
|
|
errWriterNotFound = errors.New("io.Writer not found")
|
|
)
|
|
|
|
// Add appends a new writer to the multiwriter slice
|
|
func (mw *multiWriterHolder) Add(writer io.Writer) error {
|
|
mw.mu.Lock()
|
|
defer mw.mu.Unlock()
|
|
for i := range mw.writers {
|
|
if mw.writers[i] == writer {
|
|
return errWriterAlreadyLoaded
|
|
}
|
|
}
|
|
mw.writers = append(mw.writers, writer)
|
|
return nil
|
|
}
|
|
|
|
// Remove removes existing writer from multiwriter slice
|
|
func (mw *multiWriterHolder) Remove(writer io.Writer) error {
|
|
mw.mu.Lock()
|
|
defer mw.mu.Unlock()
|
|
for i := range mw.writers {
|
|
if mw.writers[i] != writer {
|
|
continue
|
|
}
|
|
mw.writers[i] = mw.writers[len(mw.writers)-1]
|
|
mw.writers[len(mw.writers)-1] = nil
|
|
mw.writers = mw.writers[:len(mw.writers)-1]
|
|
return nil
|
|
}
|
|
return errWriterNotFound
|
|
}
|
|
|
|
// Write concurrent safe Write for each writer
|
|
func (mw *multiWriterHolder) Write(p []byte) (int, error) {
|
|
type data struct {
|
|
n int
|
|
err error
|
|
}
|
|
|
|
results := make(chan data, len(mw.writers))
|
|
mw.mu.RLock()
|
|
defer mw.mu.RUnlock()
|
|
for x := range mw.writers {
|
|
go func(w io.Writer, p []byte, ch chan<- data) {
|
|
n, err := w.Write(p)
|
|
if err != nil {
|
|
ch <- data{n, fmt.Errorf("%T %w", w, err)}
|
|
return
|
|
}
|
|
if n != len(p) {
|
|
ch <- data{n, fmt.Errorf("%T %w", w, io.ErrShortWrite)}
|
|
return
|
|
}
|
|
ch <- data{n, nil}
|
|
}(mw.writers[x], p, results)
|
|
}
|
|
|
|
for range mw.writers {
|
|
// NOTE: These results do not necessarily reflect the current io.writer
|
|
// due to the go scheduler and writer finishing at different times, the
|
|
// response coming from the channel might not match up with the for loop
|
|
// writer.
|
|
d := <-results
|
|
if d.err != nil {
|
|
return d.n, d.err
|
|
}
|
|
}
|
|
return len(p), nil
|
|
}
|
|
|
|
// multiWriter make and return a new copy of multiWriterHolder
|
|
func multiWriter(writers ...io.Writer) (*multiWriterHolder, error) {
|
|
mw := &multiWriterHolder{}
|
|
for x := range writers {
|
|
err := mw.Add(writers[x])
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
return mw, nil
|
|
}
|