Cleanup of EventLog types.
[?]
May 5, 2015, 9:26 PM
KNSI575VAW6HRCZYXOEPQ4DTSML4EORML5MV4DJBRKE7TXCPS4EACDependencies
- [2]
OV5AKJHARemove unused LogInterval type. - [3]
I2KHGVD4Require project permissions for access to most data. - [4]
7XN3I3QJAdd 'loggedIntervals' endpoint. - [5]
IZEVQF62Work in progress replacing sqlite with postgres. - [6]
7KZP4RHZSwitch from Data.Time to Data.Thyme - [7]
5DRIWGLUImproving TimeLog specs - [8]
GKGVYBZGAdded JSON serialization to TimeLog - [9]
2OIPAQCBMerge branch 'master' of github.com:nuttycom/ananke - [10]
RSEB2NFGReplacing Snap with Scotty. - [11]
64C6AWH6Rename Ananke -> Quixotic, project reboot. - [12]
OBFPJS2GProject successfully builds and tests under nix. - [13]
EZQG2APBUpdate task list. - [14]
TLQ72DSJLenses, sqlite-simple - [15]
EQXRXRZDChanged to use tasty instead of test-framework - [16]
N4NDAZYTInitial implementation of payouts. - [17]
A2J7B4SCInitial impl of depreciation function. - [18]
BROSTG5KBeginning of modularization of server. - [19]
Z7KS5XHHVery WIP. Wow. - [20]
FD7SV5I6Fix handling of event_t columns. - [21]
A6HKMINBAttempting to improve JSON handling. - [22]
2KZPOGRBOnce you get Haskell to compile, the tests pass! - [23]
TNR3TEHKSwitch to Postgres + snaplet arch compiles. - [24]
4QX5E5ACInitial compilation of payouts function succeeds. - [25]
SCXG6TJWMake log reduction safer in presence of overlapping events. - [26]
7DBNV3GVInitial, stack-based impl of time log event reduction. - [27]
NMWWP4ZNTrying out Hspec - [28]
SLL7262CMake depreciation functions more flexible. - [29]
EMVTF2IWWIP moving back to snap. - [30]
NVOCQVASInitial failing tests. - [31]
Y35QCWYWMinor improvement in WorkIndex type to eliminate duplicated information. - [32]
NTPC7KJETrivial changes, feature scratchpad. - [33]
JUUMYIQEAdd groupBy utility function for use in TimeLog.
Change contents
- edit in lib/Quixotic/Database/PostgreSQL.hs at line 8
import Data.ByteString.Char8 as B - replacement in lib/Quixotic/Database/PostgreSQL.hs at line 27
eventTypeParser :: FieldParser EventTypeeventTypeParser :: FieldParser (C.UTCTime -> LogEvent) - replacement in lib/Quixotic/Database/PostgreSQL.hs at line 31
"event_t" -> maybe (returnError UnexpectedNull f "") (nameEvent . decodeUtf8) v_ -> returnError Incompatible f "column was not of type event_t""event_t" ->let err = UnexpectedNull (B.unpack tn)(tableOid f)(maybe "" B.unpack (name f))"UTCTime -> LogEvent""columns of type event_t should not contain null values"in maybe (conversionError err) (nameEvent . decodeUtf8) v_ ->let err = Incompatible (B.unpack tn)(tableOid f)(maybe "" B.unpack (name f))"UTCTime -> LogEvent""column was not of type event_t"in conversionError err - replacement in lib/Quixotic/Database/PostgreSQL.hs at line 69
workEventParser :: RowParser WorkEventworkEventParser = WorkEvent <$> fieldWith eventTypeParser <*> fieldWith utcParser <*> fieldworkEventParser :: RowParser LogEventworkEventParser = fieldWith eventTypeParser <*> fieldWith utcParser - replacement in lib/Quixotic/Database/PostgreSQL.hs at line 73
logEntryParser = LogEntry <$> fieldWith btcAddrParser <*> workEventParserlogEntryParser = LogEntry <$> fieldWith btcAddrParser <*> workEventParser <*> field - replacement in lib/Quixotic/Database/PostgreSQL.hs at line 149
recordEvent' (ProjectId pid) (UserId uid) (LogEntry a e) = dorecordEvent' (ProjectId pid) (UserId uid) (LogEntry a e m) = do - replacement in lib/Quixotic/Database/PostgreSQL.hs at line 156[3.3665]→[3.3340:3378](∅→∅),[3.3340]→[3.3340:3378](∅→∅),[3.3378]→[3.230:263](∅→∅),[3.263]→[3.3666:3687](∅→∅),[3.3399]→[3.3666:3687](∅→∅)
, e ^. (eventType . to eventName), fromThyme $ e ^. eventTime, e ^. eventMeta, eventName e, fromThyme $ eventTime e, m - replacement in lib/Quixotic/TimeLog.hs at line 6
, btcAddr, event, EventType(..), btcAddr, event, eventMeta, LogEvent(..) - edit in lib/Quixotic/TimeLog.hs at line 9
, WorkEvent(..), eventType, eventTime, eventMeta - replacement in lib/Quixotic/TimeLog.hs at line 40
data EventType = StartWork | StopWork deriving (Show, Eq, Typeable)data LogEvent = StartWork { eventTime :: C.UTCTime }| StopWork { eventTime :: C.UTCTime }deriving (Show, Eq)makePrisms ''LogEvent - replacement in lib/Quixotic/TimeLog.hs at line 45
instance Ord EventType wherecompare StartWork StopWork = GTcompare StopWork StartWork = LTcompare _ _ = EQinstance Ord LogEvent wherecompare (StartWork t0) (StopWork t1) = if t0 == t1 then GT else compare t0 t1compare (StopWork t0) (StartWork t1) = if t0 == t1 then LT else compare t0 t1compare (StartWork t0) (StartWork t1) = compare t0 t1compare (StopWork t0) (StopWork t1) = compare t0 t1 - replacement in lib/Quixotic/TimeLog.hs at line 51
eventName :: EventType -> TexteventName StartWork = "start"eventName StopWork = "stop"eventName :: LogEvent -> TexteventName (StartWork _) = "start"eventName (StopWork _) = "stop" - replacement in lib/Quixotic/TimeLog.hs at line 55
nameEvent :: MonadPlus m => Text -> m EventTypenameEvent :: MonadPlus m => Text -> m (C.UTCTime -> LogEvent) - edit in lib/Quixotic/TimeLog.hs at line 59[3.320]→[3.1282:1283](∅→∅),[3.2736]→[3.1282:1283](∅→∅),[3.3954]→[3.1282:1283](∅→∅),[3.5515]→[3.1282:1283](∅→∅),[3.1282]→[3.1282:1283](∅→∅),[3.1283]→[3.3955:4011](∅→∅),[3.4011]→[3.863:891](∅→∅),[3.891]→[3.3879:3997](∅→∅),[3.4037]→[3.3879:3997](∅→∅),[3.3997]→[3.513:545](∅→∅),[3.545]→[3.4037:4084](∅→∅),[3.4023]→[3.4037:4084](∅→∅),[3.4037]→[3.4037:4084](∅→∅),[3.539]→[3.1406:1407](∅→∅),[3.2759]→[3.1406:1407](∅→∅),[3.1406]→[3.1406:1407](∅→∅),[3.1407]→[3.308:431](∅→∅)
data WorkEvent = WorkEvent{ _eventType :: EventType, _eventTime :: C.UTCTime-- Permit the inclusion of arbitrary JSON data that may be refactored into-- proper typed fields in the future., _eventMeta :: Maybe A.Value} deriving (Show, Eq)makeLenses ''WorkEventinstance Ord WorkEvent wherecompare a b =let cv x = (x ^. eventTime, x ^. eventType)in compare (cv a) (cv b) - replacement in lib/Quixotic/TimeLog.hs at line 62
, _event :: WorkEvent, _event :: LogEvent, _eventMeta :: Maybe A.Value - replacement in lib/Quixotic/TimeLog.hs at line 69
let ordElems e = (e ^. (event.eventTime), e ^. (event.eventType), e ^. btcAddr)let ordElems e = (e ^. event, e ^. btcAddr) - edit in lib/Quixotic/TimeLog.hs at line 103[3.492]→[3.433:489](∅→∅),[3.489]→[3.982:1011](∅→∅),[3.434]→[3.982:1011](∅→∅),[3.77]→[3.350:351](∅→∅),[3.88]→[3.350:351](∅→∅),[3.159]→[3.350:351](∅→∅),[3.434]→[3.350:351](∅→∅),[3.1011]→[3.350:351](∅→∅),[3.350]→[3.350:351](∅→∅)
type RawIndex = Map BtcAddr [Either WorkEvent Interval]type NDT = C.NominalDiffTime - edit in lib/Quixotic/TimeLog.hs at line 110
type NDT = C.NominalDiffTime - edit in lib/Quixotic/TimeLog.hs at line 151
{-|- The values of the raw index map are either complete intervals (which may be- extended if a new start is encountered at the same instant as the end of the- interval) or start events awaiting completion.-}type RawIndex = Map BtcAddr [Either LogEvent Interval] - replacement in lib/Quixotic/TimeLog.hs at line 159
appendLogEntry idx (LogEntry k ev) =let combine (WorkEvent StartWork t _) (WorkEvent StopWork t' _) | t' > t = Right $ Interval t t'combine (e1 @ (WorkEvent StartWork _ _)) (e2 @ (WorkEvent StartWork _ _)) = Left $ max e1 e2combine (e1 @ (WorkEvent StopWork _ _)) (e2 @ (WorkEvent StopWork _ _)) = Left $ min e1 e2appendLogEntry idx (LogEntry k ev _) =let combine (StartWork t) (StopWork t') | t' > t = Right $ Interval t t'combine (e1 @ (StartWork _)) (e2 @ (StartWork _)) = Left $ min e1 e2 -- ignore redundant startscombine (e1 @ (StopWork _)) (e2 @ (StopWork _)) = Left $ min e1 e2 -- ignore redundant ends - edit in lib/Quixotic/TimeLog.hs at line 164
-- if the interval includes the timestamp of a start event, then allow the extension of the intervalextension :: Interval -> LogEvent -> Maybe LogEventextension ival (StartWork t) | containsInclusive t ival = Just $ StartWork (ival ^. start)extension _ _ = Nothing - edit in lib/Quixotic/TimeLog.hs at line 171
-- if it is possible to extend an interval at the top of the stack-- because the end of that interval is the sameJust (Right ival : xs) -> case extension ival ev ofJust e' -> Left e' : xsNothing -> Left ev : Right ival : xs-- if the top element of the stack is not an interval - replacement in lib/Quixotic/TimeLog.hs at line 178
Just xs -> Left ev : xsNothing -> Left ev : []_ -> Left ev : [] - edit in lib/Quixotic/TimeLog.hs at line 186
- - replacement in server/Quixotic/Snaplet/WorkLog.hs at line 21
logWorkHandler :: EventType -> Handler App App EventIdlogWorkHandler evType = dologWorkHandler :: (C.UTCTime -> LogEvent) -> Handler App App EventIdlogWorkHandler evCtr = do - replacement in server/Quixotic/Snaplet/WorkLog.hs at line 29[3.3064]→[3.550:618](∅→∅),[3.6042]→[3.550:618](∅→∅),[3.618]→[3.4128:4208](∅→∅),[3.4460]→[3.4128:4208](∅→∅),[3.6087]→[3.4128:4208](∅→∅)
let workEvent = WorkEvent evType timestamp $ A.decode requestBodystoreEv addr = runReaderT . recordEvent pid uid $ LogEntry addr workEventlet logEntry addr = LogEntry addr (evCtr timestamp) (A.decode requestBody)storeEv addr = runReaderT . recordEvent pid uid $ logEntry addr - replacement in test/Quixotic/TimeLogSpec.hs at line 10
import Data.List.NonEmpty as Limport Data.Map.Strict as Mimport qualified Data.List.NonEmpty as Limport qualified Data.Map.Strict as M - edit in test/Quixotic/TimeLogSpec.hs at line 22
instance Arbitrary EventType wherearbitrary = elements [StartWork, StopWork]newtype EventLog = EventLog [LogEntry] - edit in test/Quixotic/TimeLogSpec.hs at line 30
newtype Intervals = Intervals (L.NonEmpty Interval)buildIntervals :: T.UTCTime -> [NominalDiffTime] -> [Interval]buildIntervals t (d : s : dx) =let ival = I.interval t (t .+^ d)in ival : buildIntervals (ival ^. end .+^ (abs s)) dxbuildIntervals _ _ = []instance Arbitrary Intervals wherearbitrary = dostartTime <- arbitrarylet deltas = filter (> 0) <$> listOf arbitraryintervals <- suchThat (buildIntervals startTime <$> deltas) (not.null)pure . Intervals $ L.fromList intervals - replacement in test/Quixotic/TimeLogSpec.hs at line 48
let record = (,) <$> arbitrary <*> (L.fromList <$> listOf1 arbitrary)let record = do addr <- arbitraryIntervals ivals <- arbitrarypure (addr, ivals) - replacement in test/Quixotic/TimeLogSpec.hs at line 67
[ parseISO8601 "2014-01-01T00:12:00Z"[ parseISO8601 "2014-01-01T00:11:59Z" - replacement in test/Quixotic/TimeLogSpec.hs at line 79
LogEntry addr <$> [WorkEvent StartWork start' Nothing, WorkEvent StopWork end' Nothing]LogEntry addr <$> [StartWork start', StopWork end'] <*> [Nothing] - replacement in test/Quixotic/TimeLogSpec.hs at line 81
expected' = fromListWith (<>) $ fmap (second pure) testIntervalsexpected' = M.fromListWith (<>) $ fmap (second pure) testIntervals - replacement in test/Quixotic/TimeLogSpec.hs at line 88
let ivalEntries addr ival = [ LogEntry addr (WorkEvent StartWork (ival ^. start) Nothing), LogEntry addr (WorkEvent StopWork (ival ^. end) Nothing) ]let ivalEntries addr ival = LogEntry addr <$> [StartWork (ival ^. start), StopWork (ival ^. end)]<*> [Nothing] - replacement in test/Quixotic/TimeLogSpec.hs at line 92
logEntries = foldrWithKey acc [] widxlogEntries = M.foldrWithKey acc [] widx - edit in test/Quixotic/TimeLogSpec.hs at line 95[3.3976]→[3.3976:4116](∅→∅),[3.1679]→[3.974:975](∅→∅),[3.4083]→[3.974:975](∅→∅),[3.4116]→[3.974:975](∅→∅),[3.4710]→[3.974:975](∅→∅)
describe "EventType serialization" $ doit "serialization is invertible" $ property $\e -> (nameEvent . eventName) e == Just e