Files
gocryptotrader/log/logger_multiwriter.go
Scott 86d3724507 Futures order position tracking & FTX scaled collateral calculation (#868)
* 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
2022-02-28 16:39:36 +11:00

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
}