/// <summary> Aliases the current stream under a certain name. </summary> private static void CmdAlias(string[] args) { if (args.Length < 1) { Console.WriteLine("Usage: alias <name>"); Console.WriteLine("Aliases current stream under provided name."); return; } var name = args[0]; if (Fetched.ContainsKey(name)) { Console.WriteLine("Stream `{0}` already exists.", name); Console.WriteLine("Use `drop {0}` to drop it.", name); return; } if (Current == null) { Console.WriteLine("No current stream to alias."); return; } Console.WriteLine("Aliased `{0}` ({1} events).", name, Current.Count); Fetched.Add(name, Current); }
/// <summary> Fetches a stream's events and places it in <see cref="Fetched"/>. </summary> private static void CmdFetch(string[] args) { if (args.Length < 2) { Console.WriteLine("Usage: fetch <name> <stream> <limit>?"); Console.WriteLine("Downloads events from remote stream, stores in-memory."); Console.WriteLine(" limit: if provided, only fetch events after this seq (included)."); return; } var name = args[0]; if (Fetched.ContainsKey(name)) { Console.WriteLine("Fetched stream `{0}` already exists.", name); Console.WriteLine("Use `drop {0}` to drop it.", name); return; } var limit = 0u; if (args.Length == 3) { if (!uint.TryParse(args[2], out limit)) { Console.WriteLine("Could not parse limit: {0}", args[2]); return; } } var sw = Stopwatch.StartNew(); var connection = new StorageConfiguration(Parse(args[1])) { ReadOnly = true }; connection.Trace = true; var driver = connection.Connect(); using (Release(driver)) { var stream = new EventStream <JObject>(driver); var list = new List <EventData>(); var start = 0L; Status("Connecting..."); Task.Run((Func <Task>)(async() => { Status("Current size:"); var maxPos = await driver.GetPositionAsync(); Console.WriteLine("Current size: {0:F2} MB", maxPos / (1024.0 * 1024.0)); Status("Current seq:"); var maxSeq = await driver.GetLastKeyAsync(); Console.WriteLine("Current seq: {0}", maxSeq); var asStatsDriver = driver as StatsDriverWrapper; var asReadOnlyDriver = (asStatsDriver?.Inner ?? driver) as ReadOnlyDriverWrapper; var asAzure = (asReadOnlyDriver?.Wrapped ?? asStatsDriver?.Inner ?? driver) as AzureStorageDriver; if (asAzure != null) { for (var i = 0; i < asAzure.Blobs.Count; ++i) { Console.WriteLine("Blob {0}: {1:F2} MB from seq {2}", asAzure.Blobs[i].Name, asAzure.Blobs[i].Properties.Length / (1024.0 * 1024.0), i < asAzure.FirstKey.Count ? asAzure.FirstKey[i] : maxSeq); } } if (limit > 0) { Status($"Moving to seq {limit} .."); await stream.DiscardUpTo(limit); start = stream.Position; } Func <bool> more; do { var fetch = stream.BackgroundFetchAsync(); JObject obj; while ((obj = stream.TryGetNext()) != null) { list.Add(new EventData(stream.Sequence, obj)); } Status("Fetching: {0}/{1} ({2:F2}/{3:F2} MB)", stream.Sequence, maxSeq, (stream.Position - start) / (1024.0 * 1024.0), (maxPos - start) / (1024.0 * 1024.0)); more = await fetch; } while (more()); })).Wait(); Console.WriteLine("Fetched `{0}` ({1} events, {2:F2} MB) in {3:F2}s.", name, list.Count, (stream.Position - start) / (1024.0 * 1024.0), sw.ElapsedMilliseconds / 1000.0); Fetched.Add(name, list); Peek(list); if (Current == null) { Current = list; } } }