A fuckload of Mongo

Starting to take shape with some nice perf gains.
This commit is contained in:
Thomas Hounsell 2015-09-09 23:48:29 +01:00
parent 34141f60f1
commit 2919fbea16
17 changed files with 850 additions and 645 deletions

View File

@ -11,311 +11,290 @@
namespace BuildFeed.Controllers namespace BuildFeed.Controllers
{ {
public class frontController : Controller public class frontController : Controller
{ {
public const int PAGE_SIZE = 96; public const int PAGE_SIZE = 96;
[Route("", Order = 1)] [Route("", Order = 1)]
#if !DEBUG #if !DEBUG
[OutputCache(Duration = 600, VaryByParam = "none", VaryByCustom = "userName")] [OutputCache(Duration = 600, VaryByParam = "none", VaryByCustom = "userName")]
#endif #endif
public ActionResult index() { return indexPage(1); } public ActionResult index() { return indexPage(1); }
[Route("page-{page:int:min(2)}/", Order = 0)] [Route("page-{page:int:min(2)}/", Order = 0)]
#if !DEBUG #if !DEBUG
[OutputCache(Duration = 600, VaryByParam = "page", VaryByCustom = "userName")] [OutputCache(Duration = 600, VaryByParam = "page", VaryByCustom = "userName")]
#endif #endif
public ActionResult indexPage(int page) public ActionResult indexPage(int page)
{ {
var buildGroups = (from b in new Build().Select() Build bModel = new Build();
group b by new BuildGroup var buildGroups = bModel.SelectBuildGroups(PAGE_SIZE, (page - 1) * PAGE_SIZE);
{
Major = b.MajorVersion,
Minor = b.MinorVersion,
Build = b.Number,
Revision = b.Revision
}
into bg
orderby bg.Key.Major descending,
bg.Key.Minor descending,
bg.Key.Build descending,
bg.Key.Revision descending
select new FrontBuildGroup
{
Key = bg.Key,
LastBuild = bg.Max(m => m.BuildTime),
BuildCount = bg.Count()
}).ToArray();
ViewBag.PageNumber = page; ViewBag.PageNumber = page;
ViewBag.PageCount = Math.Ceiling(Convert.ToDouble(buildGroups.Length) / Convert.ToDouble(PAGE_SIZE)); ViewBag.PageCount = Math.Ceiling(
Convert.ToDouble(bModel.SelectBuildGroupsCount()) /
Convert.ToDouble(PAGE_SIZE));
if (ViewBag.PageNumber > ViewBag.PageCount) if (ViewBag.PageCount != 0 && ViewBag.PageNumber > ViewBag.PageCount)
{
return new HttpNotFoundResult();
}
return View("index", buildGroups);
}
[Route("group/{major}.{minor}.{number}.{revision}/")]
#if !DEBUG
[OutputCache(Duration = 600, VaryByParam = "none", VaryByCustom = "userName")]
#endif
public ActionResult viewGroup(byte major, byte minor, ushort number, ushort? revision = null)
{
Build bModel = new Build();
var builds = bModel.SelectSingleBuildGroup(new BuildGroup()
{
Major = major,
Minor = minor,
Build = number,
Revision = revision
});
return builds.Item2.Count() == 1 ?
RedirectToAction("viewBuild", new { id = builds.Item2.Single().Id }) as ActionResult :
View(builds);
}
[Route("build/{id}/", Name = "Build")]
#if !DEBUG
[OutputCache(Duration = 600, VaryByParam = "none", VaryByCustom = "userName")]
#endif
public ActionResult viewBuild(Guid id)
{
BuildModel b = new Build().SelectById(id);
return View(b);
}
[Route("twitter/{id}/")]
#if !DEBUG
[OutputCache(Duration = 600, VaryByParam = "none")]
[CustomContentType(ContentType = "image/png", Order = 2)]
#endif
public ActionResult twitterCard(Guid id)
{
BuildModel b = new Build().SelectById(id);
using (Bitmap bm = new Bitmap(560, 300))
{
using (Graphics gr = Graphics.FromImage(bm))
{ {
return new HttpNotFoundResult(); GraphicsPath gp = new GraphicsPath();
gr.CompositingMode = CompositingMode.SourceOver;
gr.CompositingQuality = CompositingQuality.HighQuality;
gr.InterpolationMode = InterpolationMode.HighQualityBicubic;
gr.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
gr.SmoothingMode = SmoothingMode.HighQuality;
gr.PixelOffsetMode = PixelOffsetMode.HighQuality;
gr.FillRectangle(new SolidBrush(Color.FromArgb(0x27, 0x2b, 0x30)), 0, 0, 560, 300);
gp.AddString("BUILDFEED", new FontFamily("Segoe UI"), (int)FontStyle.Bold, 16, new Point(20, 20), StringFormat.GenericTypographic);
gp.AddString($"Windows NT {b.MajorVersion}.{b.MinorVersion} build", new FontFamily("Segoe UI"), 0, 24, new Point(20, 40), StringFormat.GenericTypographic);
gp.AddString(b.Number.ToString(), new FontFamily("Segoe UI Light"), 0, 180, new Point(12, 20), StringFormat.GenericTypographic);
gp.AddString($"{b.Lab}", new FontFamily("Segoe UI"), 0, 40, new Point(16, 220), StringFormat.GenericTypographic);
gr.FillPath(Brushes.White, gp);
Response.ContentType = "image/png";
bm.Save(Response.OutputStream, ImageFormat.Png);
}
}
return new EmptyResult();
}
[Route("lab/{lab}/", Order = 1, Name = "Lab Root")]
#if !DEBUG
[OutputCache(Duration = 600, VaryByParam = "none", VaryByCustom = "userName")]
#endif
public ActionResult viewLab(string lab) { return viewLabPage(lab, 1); }
[Route("lab/{lab}/page-{page:int:min(2)}/", Order = 0)]
#if !DEBUG
[OutputCache(Duration = 600, VaryByParam = "page", VaryByCustom = "userName")]
#endif
public ActionResult viewLabPage(string lab, int page)
{
ViewBag.MetaItem = new MetaItem().SelectById(new MetaItemKey
{
Type = MetaType.Lab,
Value = lab
});
ViewBag.ItemId = lab;
var builds = new Build().SelectLabInBuildOrder(lab, (page - 1) * PAGE_SIZE, PAGE_SIZE);
ViewBag.PageNumber = page;
ViewBag.PageCount = Math.Ceiling(Convert.ToDouble(builds.Count) / Convert.ToDouble(PAGE_SIZE));
if (ViewBag.PageNumber > ViewBag.PageCount)
{
return new HttpNotFoundResult();
}
return View("viewLab", builds);
}
[Route("source/{source}/", Order = 1, Name = "Source Root")]
#if !DEBUG
[OutputCache(Duration = 600, VaryByParam = "none", VaryByCustom = "userName")]
#endif
public ActionResult viewSource(TypeOfSource source) { return viewSourcePage(source, 1); }
[Route("source/{source}/page-{page:int:min(2)}/", Order = 0)]
#if !DEBUG
[OutputCache(Duration = 600, VaryByParam = "page", VaryByCustom = "userName")]
#endif
public ActionResult viewSourcePage(TypeOfSource source, int page)
{
ViewBag.MetaItem = new MetaItem().SelectById(new MetaItemKey
{
Type = MetaType.Source,
Value = source.ToString()
});
ViewBag.ItemId = DisplayHelpers.GetDisplayTextForEnum(source);
var builds = new Build().SelectInBuildOrder().Where(b => b.SourceType == source).ToArray();
ViewBag.PageNumber = page;
ViewBag.PageCount = Math.Ceiling(Convert.ToDouble(builds.Length) / Convert.ToDouble(PAGE_SIZE));
if (ViewBag.PageNumber > ViewBag.PageCount)
{
return new HttpNotFoundResult();
}
return View("viewSource", builds.Skip((page - 1) * PAGE_SIZE).Take(PAGE_SIZE));
}
[Route("year/{year}/", Order = 1, Name = "Year Root")]
#if !DEBUG
[OutputCache(Duration = 600, VaryByParam = "none", VaryByCustom = "userName")]
#endif
public ActionResult viewYear(int year) { return viewYearPage(year, 1); }
[Route("year/{year}/page-{page:int:min(2)}/", Order = 0)]
#if !DEBUG
[OutputCache(Duration = 600, VaryByParam = "page", VaryByCustom = "userName")]
#endif
public ActionResult viewYearPage(int year, int page)
{
ViewBag.MetaItem = new MetaItem().SelectById(new MetaItemKey
{
Type = MetaType.Year,
Value = year.ToString()
});
ViewBag.ItemId = year.ToString();
var builds = new Build().SelectInBuildOrder().Where(b => b.BuildTime.HasValue && b.BuildTime.Value.Year == year).ToArray();
ViewBag.PageNumber = page;
ViewBag.PageCount = Math.Ceiling(Convert.ToDouble(builds.Length) / Convert.ToDouble(PAGE_SIZE));
if (ViewBag.PageNumber > ViewBag.PageCount)
{
return new HttpNotFoundResult();
}
return View("viewYear", builds.Skip((page - 1) * PAGE_SIZE).Take(PAGE_SIZE));
}
[Route("version/{major}.{minor}/", Order = 1, Name = "Version Root")]
#if !DEBUG
[OutputCache(Duration = 600, VaryByParam = "none", VaryByCustom = "userName")]
#endif
public ActionResult viewVersion(int major, int minor) { return viewVersionPage(major, minor, 1); }
[Route("version/{major}.{minor}/page-{page:int:min(2)}/", Order = 0)]
#if !DEBUG
[OutputCache(Duration = 600, VaryByParam = "none", VaryByCustom = "userName")]
#endif
public ActionResult viewVersionPage(int major, int minor, int page)
{
string valueString = $"{major}.{minor}";
ViewBag.MetaItem = new MetaItem().SelectById(new MetaItemKey
{
Type = MetaType.Version,
Value = valueString
});
ViewBag.ItemId = valueString;
var builds = new Build().SelectInBuildOrder().Where(b => b.MajorVersion == major && b.MinorVersion == minor).ToArray();
ViewBag.PageNumber = page;
ViewBag.PageCount = Math.Ceiling(Convert.ToDouble(builds.Length) / Convert.ToDouble(PAGE_SIZE));
if (ViewBag.PageNumber > ViewBag.PageCount)
{
return new HttpNotFoundResult();
}
return View("viewVersion", builds.Skip((page - 1) * PAGE_SIZE).Take(PAGE_SIZE));
}
[Route("add/"), Authorize]
public ActionResult addBuild() { return View("editBuild"); }
[Route("add/"), Authorize, HttpPost]
public ActionResult addBuild(BuildModel build)
{
if (ModelState.IsValid)
{
try
{
build.Added = DateTime.Now;
build.Modified = DateTime.Now;
new Build().Insert(build);
}
catch
{
return View("editBuild", build);
}
return RedirectToAction("viewBuild", new
{
id = build.Id
});
}
return View("editBuild", build);
}
[Route("edit/{id}/"), Authorize]
public ActionResult editBuild(Guid id)
{
BuildModel b = new Build().SelectById(id);
return View(b);
}
[Route("edit/{id}/"), Authorize, HttpPost]
public ActionResult editBuild(long id, BuildModel build)
{
if (ModelState.IsValid)
{
try
{
new Build().Update(build);
}
catch
{
return View(build);
} }
return View("index", buildGroups.Skip((page - 1) * PAGE_SIZE).Take(PAGE_SIZE)); return RedirectToAction("viewBuild", new { id = build.Id });
} }
return View(build);
}
[Route("group/{major}.{minor}.{number}.{revision}/")] [Route("delete/{id}/"), Authorize(Roles = "Administrators")]
#if !DEBUG public ActionResult deleteBuild(Guid id)
[OutputCache(Duration = 600, VaryByParam = "none", VaryByCustom = "userName")] {
#endif new Build().DeleteById(id);
public ActionResult viewGroup(byte major, byte minor, ushort number, ushort? revision = null) return RedirectToAction("index");
{ }
var builds = (from b in new Build().Select() }
group b by new BuildGroup
{
Major = b.MajorVersion,
Minor = b.MinorVersion,
Build = b.Number,
Revision = b.Revision
}
into bg
where bg.Key.Major == major
where bg.Key.Minor == minor
where bg.Key.Build == number
where bg.Key.Revision == revision
select bg).Single();
return builds.Count() == 1 ?
RedirectToAction("viewBuild", new {id = builds.Single().Id}) as ActionResult :
View(builds);
}
[Route("build/{id}/", Name = "Build")]
#if !DEBUG
[OutputCache(Duration = 600, VaryByParam = "none", VaryByCustom = "userName")]
#endif
public ActionResult viewBuild(Guid id)
{
BuildModel b = new Build().SelectById(id);
return View(b);
}
[Route("twitter/{id}/")]
#if !DEBUG
[OutputCache(Duration = 600, VaryByParam = "none")]
[CustomContentType(ContentType = "image/png", Order = 2)]
#endif
public ActionResult twitterCard(Guid id)
{
BuildModel b = new Build().SelectById(id);
using (Bitmap bm = new Bitmap(560, 300))
{
using (Graphics gr = Graphics.FromImage(bm))
{
GraphicsPath gp = new GraphicsPath();
gr.CompositingMode = CompositingMode.SourceOver;
gr.CompositingQuality = CompositingQuality.HighQuality;
gr.InterpolationMode = InterpolationMode.HighQualityBicubic;
gr.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
gr.SmoothingMode = SmoothingMode.HighQuality;
gr.PixelOffsetMode = PixelOffsetMode.HighQuality;
gr.FillRectangle(new SolidBrush(Color.FromArgb(0x27, 0x2b, 0x30)), 0, 0, 560, 300);
gp.AddString("BUILDFEED", new FontFamily("Segoe UI"), (int) FontStyle.Bold, 16, new Point(20, 20), StringFormat.GenericTypographic);
gp.AddString($"Windows NT {b.MajorVersion}.{b.MinorVersion} build", new FontFamily("Segoe UI"), 0, 24, new Point(20, 40), StringFormat.GenericTypographic);
gp.AddString(b.Number.ToString(), new FontFamily("Segoe UI Light"), 0, 180, new Point(12, 20), StringFormat.GenericTypographic);
gp.AddString($"{b.Lab}", new FontFamily("Segoe UI"), 0, 40, new Point(16, 220), StringFormat.GenericTypographic);
gr.FillPath(Brushes.White, gp);
Response.ContentType = "image/png";
bm.Save(Response.OutputStream, ImageFormat.Png);
}
}
return new EmptyResult();
}
[Route("lab/{lab}/", Order = 1, Name = "Lab Root")]
#if !DEBUG
[OutputCache(Duration = 600, VaryByParam = "none", VaryByCustom = "userName")]
#endif
public ActionResult viewLab(string lab) { return viewLabPage(lab, 1); }
[Route("lab/{lab}/page-{page:int:min(2)}/", Order = 0)]
#if !DEBUG
[OutputCache(Duration = 600, VaryByParam = "page", VaryByCustom = "userName")]
#endif
public ActionResult viewLabPage(string lab, int page)
{
ViewBag.MetaItem = new MetaItem().SelectById(new MetaItemKey
{
Type = MetaType.Lab,
Value = lab
});
ViewBag.ItemId = lab;
var builds = new Build().SelectInBuildOrder().Where(b => b.Lab != null && (b.Lab.ToLower() == lab.ToLower())).ToArray();
ViewBag.PageNumber = page;
ViewBag.PageCount = Math.Ceiling(Convert.ToDouble(builds.Length) / Convert.ToDouble(PAGE_SIZE));
if (ViewBag.PageNumber > ViewBag.PageCount)
{
return new HttpNotFoundResult();
}
return View("viewLab", builds.Skip((page - 1) * PAGE_SIZE).Take(PAGE_SIZE));
}
[Route("source/{source}/", Order = 1, Name = "Source Root")]
#if !DEBUG
[OutputCache(Duration = 600, VaryByParam = "none", VaryByCustom = "userName")]
#endif
public ActionResult viewSource(TypeOfSource source) { return viewSourcePage(source, 1); }
[Route("source/{source}/page-{page:int:min(2)}/", Order = 0)]
#if !DEBUG
[OutputCache(Duration = 600, VaryByParam = "page", VaryByCustom = "userName")]
#endif
public ActionResult viewSourcePage(TypeOfSource source, int page)
{
ViewBag.MetaItem = new MetaItem().SelectById(new MetaItemKey
{
Type = MetaType.Source,
Value = source.ToString()
});
ViewBag.ItemId = DisplayHelpers.GetDisplayTextForEnum(source);
var builds = new Build().SelectInBuildOrder().Where(b => b.SourceType == source).ToArray();
ViewBag.PageNumber = page;
ViewBag.PageCount = Math.Ceiling(Convert.ToDouble(builds.Length) / Convert.ToDouble(PAGE_SIZE));
if (ViewBag.PageNumber > ViewBag.PageCount)
{
return new HttpNotFoundResult();
}
return View("viewSource", builds.Skip((page - 1) * PAGE_SIZE).Take(PAGE_SIZE));
}
[Route("year/{year}/", Order = 1, Name = "Year Root")]
#if !DEBUG
[OutputCache(Duration = 600, VaryByParam = "none", VaryByCustom = "userName")]
#endif
public ActionResult viewYear(int year) { return viewYearPage(year, 1); }
[Route("year/{year}/page-{page:int:min(2)}/", Order = 0)]
#if !DEBUG
[OutputCache(Duration = 600, VaryByParam = "page", VaryByCustom = "userName")]
#endif
public ActionResult viewYearPage(int year, int page)
{
ViewBag.MetaItem = new MetaItem().SelectById(new MetaItemKey
{
Type = MetaType.Year,
Value = year.ToString()
});
ViewBag.ItemId = year.ToString();
var builds = new Build().SelectInBuildOrder().Where(b => b.BuildTime.HasValue && b.BuildTime.Value.Year == year).ToArray();
ViewBag.PageNumber = page;
ViewBag.PageCount = Math.Ceiling(Convert.ToDouble(builds.Length) / Convert.ToDouble(PAGE_SIZE));
if (ViewBag.PageNumber > ViewBag.PageCount)
{
return new HttpNotFoundResult();
}
return View("viewYear", builds.Skip((page - 1) * PAGE_SIZE).Take(PAGE_SIZE));
}
[Route("version/{major}.{minor}/", Order = 1, Name = "Version Root")]
#if !DEBUG
[OutputCache(Duration = 600, VaryByParam = "none", VaryByCustom = "userName")]
#endif
public ActionResult viewVersion(int major, int minor) { return viewVersionPage(major, minor, 1); }
[Route("version/{major}.{minor}/page-{page:int:min(2)}/", Order = 0)]
#if !DEBUG
[OutputCache(Duration = 600, VaryByParam = "none", VaryByCustom = "userName")]
#endif
public ActionResult viewVersionPage(int major, int minor, int page)
{
string valueString = $"{major}.{minor}";
ViewBag.MetaItem = new MetaItem().SelectById(new MetaItemKey
{
Type = MetaType.Version,
Value = valueString
});
ViewBag.ItemId = valueString;
var builds = new Build().SelectInBuildOrder().Where(b => b.MajorVersion == major && b.MinorVersion == minor).ToArray();
ViewBag.PageNumber = page;
ViewBag.PageCount = Math.Ceiling(Convert.ToDouble(builds.Length) / Convert.ToDouble(PAGE_SIZE));
if (ViewBag.PageNumber > ViewBag.PageCount)
{
return new HttpNotFoundResult();
}
return View("viewVersion", builds.Skip((page - 1) * PAGE_SIZE).Take(PAGE_SIZE));
}
[Route("add/"), Authorize]
public ActionResult addBuild() { return View("editBuild"); }
[Route("add/"), Authorize, HttpPost]
public ActionResult addBuild(BuildModel build)
{
if (ModelState.IsValid)
{
try
{
build.Added = DateTime.Now;
build.Modified = DateTime.Now;
new Build().Insert(build);
}
catch
{
return View("editBuild", build);
}
return RedirectToAction("viewBuild", new
{
id = build.Id
});
}
return View("editBuild", build);
}
[Route("edit/{id}/"), Authorize]
public ActionResult editBuild(Guid id)
{
BuildModel b = new Build().SelectById(id);
return View(b);
}
[Route("edit/{id}/"), Authorize, HttpPost]
public ActionResult editBuild(long id, BuildModel build)
{
if (ModelState.IsValid)
{
try
{
new Build().Update(build);
}
catch
{
return View(build);
}
return RedirectToAction("viewBuild", new { id = build.Id });
}
return View(build);
}
[Route("delete/{id}/"), Authorize(Roles = "Administrators")]
public ActionResult deleteBuild(Guid id)
{
new Build().DeleteById(id);
return RedirectToAction("index");
}
}
} }

View File

@ -1,333 +1,414 @@
using System; using BuildFeed.Local;
using BuildFeed.Models.ViewModel.Front;
using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;
using MongoDB.Driver;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using Required = System.ComponentModel.DataAnnotations.RequiredAttribute;
using System.Web.Mvc; using System.Web.Mvc;
using BuildFeed.Local; using Required = System.ComponentModel.DataAnnotations.RequiredAttribute;
using MongoDB.Driver;
using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;
namespace BuildFeed.Models namespace BuildFeed.Models
{ {
[DataObject] [DataObject]
public class BuildModel public class BuildModel
{ {
[Key, BsonId] [Key, BsonId]
public Guid Id { get; set; } public Guid Id { get; set; }
public long? LegacyId { get; set; } public long? LegacyId { get; set; }
[@Required] [@Required]
[Display(ResourceType = typeof(Model), Name = "MajorVersion")] [Display(ResourceType = typeof(Model), Name = "MajorVersion")]
public byte MajorVersion { get; set; } public byte MajorVersion { get; set; }
[@Required] [@Required]
[Display(ResourceType = typeof(Model), Name = "MinorVersion")] [Display(ResourceType = typeof(Model), Name = "MinorVersion")]
public byte MinorVersion { get; set; } public byte MinorVersion { get; set; }
[@Required] [@Required]
[Display(ResourceType = typeof(Model), Name = "Number")] [Display(ResourceType = typeof(Model), Name = "Number")]
public ushort Number { get; set; } public ushort Number { get; set; }
[Display(ResourceType = typeof(Model), Name = "Revision")] [Display(ResourceType = typeof(Model), Name = "Revision")]
[DisplayFormat(ConvertEmptyStringToNull = true)] [DisplayFormat(ConvertEmptyStringToNull = true)]
public ushort? Revision { get; set; } public ushort? Revision { get; set; }
[Display(ResourceType = typeof(Model), Name = "Lab")] [Display(ResourceType = typeof(Model), Name = "Lab")]
public string Lab { get; set; } public string Lab { get; set; }
[Display(ResourceType = typeof(Model), Name = "BuildTime")] [Display(ResourceType = typeof(Model), Name = "BuildTime")]
[DisplayFormat(ConvertEmptyStringToNull = true, ApplyFormatInEditMode = true, DataFormatString = "{0:yyMMdd-HHmm}")] [DisplayFormat(ConvertEmptyStringToNull = true, ApplyFormatInEditMode = true, DataFormatString = "{0:yyMMdd-HHmm}")]
public DateTime? BuildTime { get; set; } public DateTime? BuildTime { get; set; }
[@Required] [@Required]
[Display(ResourceType = typeof(Model), Name = "Added")] [Display(ResourceType = typeof(Model), Name = "Added")]
public DateTime Added { get; set; } public DateTime Added { get; set; }
[@Required] [@Required]
[Display(ResourceType = typeof(Model), Name = "Modified")] [Display(ResourceType = typeof(Model), Name = "Modified")]
public DateTime Modified { get; set; } public DateTime Modified { get; set; }
[@Required] [@Required]
[Display(ResourceType = typeof(Model), Name = "SourceType")] [Display(ResourceType = typeof(Model), Name = "SourceType")]
[EnumDataType(typeof(TypeOfSource))] [EnumDataType(typeof(TypeOfSource))]
public TypeOfSource SourceType { get; set; } public TypeOfSource SourceType { get; set; }
[Display(ResourceType = typeof(Model), Name = "SourceDetails")] [Display(ResourceType = typeof(Model), Name = "SourceDetails")]
[AllowHtml] [AllowHtml]
public string SourceDetails { get; set; } public string SourceDetails { get; set; }
[Display(ResourceType = typeof(Model), Name = "LeakDate")] [Display(ResourceType = typeof(Model), Name = "LeakDate")]
[DisplayFormat(ConvertEmptyStringToNull = true, ApplyFormatInEditMode = true, DataFormatString = "{0:dd/MM/yyyy}")] [DisplayFormat(ConvertEmptyStringToNull = true, ApplyFormatInEditMode = true, DataFormatString = "{0:dd/MM/yyyy}")]
public DateTime? LeakDate { get; set; } public DateTime? LeakDate { get; set; }
[Display(ResourceType = typeof(Model), Name = "FlightLevel")] [Display(ResourceType = typeof(Model), Name = "FlightLevel")]
[EnumDataType(typeof(LevelOfFlight))] [EnumDataType(typeof(LevelOfFlight))]
public LevelOfFlight FlightLevel { get; set; } public LevelOfFlight FlightLevel { get; set; }
public bool IsLeaked public bool IsLeaked
{ {
get get
{
switch (SourceType)
{ {
switch (SourceType) case TypeOfSource.PublicRelease:
{ case TypeOfSource.InternalLeak:
case TypeOfSource.PublicRelease: case TypeOfSource.UpdateGDR:
case TypeOfSource.InternalLeak: case TypeOfSource.UpdateLDR:
case TypeOfSource.UpdateGDR: return true;
case TypeOfSource.UpdateLDR: default:
return true; return false;
default:
return false;
}
} }
} }
}
public string FullBuildString public string FullBuildString
{ {
get get
{
StringBuilder sb = new StringBuilder();
sb.AppendFormat("{0}.{1}.{2}", MajorVersion, MinorVersion, Number);
if (Revision.HasValue)
{ {
StringBuilder sb = new StringBuilder(); sb.AppendFormat(".{0}", Revision);
sb.AppendFormat("{0}.{1}.{2}", MajorVersion, MinorVersion, Number);
if (Revision.HasValue)
{
sb.AppendFormat(".{0}", Revision);
}
if (!string.IsNullOrWhiteSpace(Lab))
{
sb.AppendFormat(".{0}", Lab);
}
if (BuildTime.HasValue)
{
sb.AppendFormat(".{0:yyMMdd-HHmm}", BuildTime);
}
return sb.ToString();
} }
}
}
public class Build if (!string.IsNullOrWhiteSpace(Lab))
{
private const string _buildCollectionName = "builds";
private MongoClient _dbClient;
private IMongoCollection<BuildModel> _buildCollection;
public Build()
{
_dbClient = new MongoClient(new MongoClientSettings()
{ {
Server = new MongoServerAddress(MongoConfig.Host, MongoConfig.Port) sb.AppendFormat(".{0}", Lab);
}); }
_buildCollection = _dbClient.GetDatabase(MongoConfig.Database).GetCollection<BuildModel>(_buildCollectionName); if (BuildTime.HasValue)
} {
sb.AppendFormat(".{0:yyMMdd-HHmm}", BuildTime);
}
[DataObjectMethod(DataObjectMethodType.Select, true)] return sb.ToString();
public IEnumerable<BuildModel> Select() }
{ }
var task = _buildCollection.Find(new BsonDocument()).ToListAsync(); }
task.Wait();
return task.Result;
}
[DataObjectMethod(DataObjectMethodType.Select, false)] public class Build
public BuildModel SelectById(Guid id) {
{ private const string _buildCollectionName = "builds";
var task = _buildCollection.Find(f => f.Id == id).SingleOrDefaultAsync();
task.Wait();
return task.Result;
}
[DataObjectMethod(DataObjectMethodType.Select, false)] private MongoClient _dbClient;
public BuildModel SelectByLegacyId(long id) private IMongoCollection<BuildModel> _buildCollection;
{
var task = _buildCollection.Find(f => f.LegacyId == id).SingleOrDefaultAsync();
task.Wait();
return task.Result;
}
[DataObjectMethod(DataObjectMethodType.Select, false)] public Build()
public IEnumerable<BuildModel> SelectInBuildOrder() {
{ _dbClient = new MongoClient(new MongoClientSettings()
var task = _buildCollection.Find(new BsonDocument()) {
.SortByDescending(b => b.BuildTime) Server = new MongoServerAddress(MongoConfig.Host, MongoConfig.Port)
.ThenByDescending(b => b.MajorVersion) });
.ThenByDescending(b => b.MinorVersion)
.ThenByDescending(b => b.Number)
.ThenByDescending(b => b.Revision)
.ToListAsync();
task.Wait();
return task.Result;
}
[DataObjectMethod(DataObjectMethodType.Select, false)] _buildCollection = _dbClient.GetDatabase(MongoConfig.Database).GetCollection<BuildModel>(_buildCollectionName);
public IEnumerable<BuildModel> SelectInVersionOrder() }
{
var task = _buildCollection.Find(new BsonDocument())
.SortByDescending(b => b.MajorVersion)
.ThenByDescending(b => b.MinorVersion)
.ThenByDescending(b => b.Number)
.ThenByDescending(b => b.Revision)
.ThenByDescending(b => b.BuildTime)
.ToListAsync();
task.Wait();
return task.Result;
}
[DataObjectMethod(DataObjectMethodType.Select, false)] [DataObjectMethod(DataObjectMethodType.Select, true)]
public IEnumerable<BuildVersion> SelectBuildVersions() public List<BuildModel> Select()
{ {
var task = _buildCollection.DistinctAsync(b => new BuildVersion() { Major = b.MajorVersion, Minor = b.MinorVersion }, b => true); var task = _buildCollection.Find(new BsonDocument()).ToListAsync();
task.Wait(); task.Wait();
var outTask = task.Result.ToListAsync(); return task.Result;
outTask.Wait(); }
return outTask.Result
.OrderByDescending(y => y.Major)
.ThenByDescending(y => y.Minor);
}
[DataObjectMethod(DataObjectMethodType.Select, false)] [DataObjectMethod(DataObjectMethodType.Select, false)]
public IEnumerable<int> SelectBuildYears() public List<FrontBuildGroup> SelectBuildGroups(int limit, int skip)
{ {
var task = _buildCollection.DistinctAsync(b => b.BuildTime.Value.Year, b => b.BuildTime.HasValue); var pipeline = _buildCollection.Aggregate()
task.Wait(); .Group(b => new BuildGroup()
var outTask = task.Result.ToListAsync(); {
outTask.Wait(); Major = b.MajorVersion,
return outTask.Result.OrderBy(b => b); Minor = b.MinorVersion,
} Build = b.Number,
Revision = b.Revision
},
bg => new FrontBuildGroup()
{
Key = bg.Key,
BuildCount = bg.Count(),
LastBuild = bg.Max(b => b.BuildTime)
})
.SortByDescending(b => b.Key.Major)
.ThenByDescending(b => b.Key.Minor)
.ThenByDescending(b => b.Key.Build)
.ThenByDescending(b => b.Key.Revision)
.Skip(skip)
.Limit(limit);
[DataObjectMethod(DataObjectMethodType.Select, false)] var task = pipeline.ToListAsync();
public IEnumerable<string> SelectBuildLabs() task.Wait();
{
var task = _buildCollection.DistinctAsync(b => b.Lab.ToLower(), b => !string.IsNullOrWhiteSpace(b.Lab));
task.Wait();
var outTask = task.Result.ToListAsync();
outTask.Wait();
return outTask.Result.OrderBy(b => b);
}
[DataObjectMethod(DataObjectMethodType.Select, false)] return task.Result;
public IEnumerable<string> SelectBuildLabs(byte major, byte minor) }
{
var task = _buildCollection.DistinctAsync(b => b.Lab.ToLower(), b => !string.IsNullOrWhiteSpace(b.Lab) && b.MajorVersion == major && b.MinorVersion == minor);
task.Wait();
var outTask = task.Result.ToListAsync();
outTask.Wait();
return outTask.Result.OrderBy(b => b);
}
[DataObjectMethod(DataObjectMethodType.Insert, true)] [DataObjectMethod(DataObjectMethodType.Select, true)]
public void Insert(BuildModel item) public int SelectBuildGroupsCount()
{ {
item.Id = Guid.NewGuid(); var pipeline = _buildCollection.Aggregate()
var task = _buildCollection.InsertOneAsync(item); .Group(b => new BuildGroup()
task.Wait(); {
} Major = b.MajorVersion,
Minor = b.MinorVersion,
Build = b.Number,
Revision = b.Revision
},
bg => new BsonDocument());
[DataObjectMethod(DataObjectMethodType.Update, true)] var task = pipeline.ToListAsync();
public void Update(BuildModel item) task.Wait();
{
BuildModel old = SelectById(item.Id);
item.Added = old.Added;
item.Modified = DateTime.Now;
var task = _buildCollection.ReplaceOneAsync(f => f.Id == item.Id, item); return task.Result.Count();
task.Wait(); }
}
[DataObjectMethod(DataObjectMethodType.Insert, false)] [DataObjectMethod(DataObjectMethodType.Select, false)]
public void InsertAll(IEnumerable<BuildModel> items) public Tuple<BuildGroup, IEnumerable<BuildModel>> SelectSingleBuildGroup(BuildGroup bGroup)
{ {
var task = _buildCollection.InsertManyAsync(items); var pipeline = _buildCollection.Aggregate()
task.Wait(); .Match(b => b.MajorVersion == bGroup.Major)
} .Match(b => b.MinorVersion == bGroup.Minor)
.Match(b => b.Number == bGroup.Build)
.Match(b => b.Revision == bGroup.Revision)
.SortByDescending(b => b.BuildTime);
[DataObjectMethod(DataObjectMethodType.Delete, true)] var task = pipeline.ToListAsync();
public void DeleteById(Guid id) task.Wait();
{
var task = _buildCollection.DeleteOneAsync(f => f.Id == id);
task.Wait();
}
}
public enum TypeOfSource return new Tuple<BuildGroup, IEnumerable<BuildModel>>(bGroup, task.Result);
{ }
[Display(ResourceType = typeof(Model), Name = "PublicRelease")]
PublicRelease,
[Display(ResourceType = typeof(Model), Name = "InternalLeak")] [DataObjectMethod(DataObjectMethodType.Select, false)]
InternalLeak, public BuildModel SelectById(Guid id)
{
var task = _buildCollection.Find(f => f.Id == id).SingleOrDefaultAsync();
task.Wait();
return task.Result;
}
[Display(ResourceType = typeof(Model), Name = "UpdateGDR")] [DataObjectMethod(DataObjectMethodType.Select, false)]
UpdateGDR, public BuildModel SelectByLegacyId(long id)
{
var task = _buildCollection.Find(f => f.LegacyId == id).SingleOrDefaultAsync();
task.Wait();
return task.Result;
}
[Display(ResourceType = typeof(Model), Name = "UpdateLDR")] [DataObjectMethod(DataObjectMethodType.Select, false)]
UpdateLDR, public IEnumerable<BuildModel> SelectInBuildOrder()
{
var task = _buildCollection.Find(new BsonDocument())
.SortByDescending(b => b.BuildTime)
.ThenByDescending(b => b.MajorVersion)
.ThenByDescending(b => b.MinorVersion)
.ThenByDescending(b => b.Number)
.ThenByDescending(b => b.Revision)
.ToListAsync();
task.Wait();
return task.Result;
}
[Display(ResourceType = typeof(Model), Name = "AppPackage")] [DataObjectMethod(DataObjectMethodType.Select, false)]
AppPackage, public List<BuildModel> SelectLabInBuildOrder(string lab, int skip, int limit)
{
var task = _buildCollection.Find(b => b.Lab != null && (b.Lab.ToLower() == lab.ToLower()))
.SortByDescending(b => b.BuildTime)
.ThenByDescending(b => b.MajorVersion)
.ThenByDescending(b => b.MinorVersion)
.ThenByDescending(b => b.Number)
.ThenByDescending(b => b.Revision)
.Skip(skip)
.Limit(limit)
.ToListAsync();
task.Wait();
return task.Result;
}
[Display(ResourceType = typeof(Model), Name = "BuildTools")] [DataObjectMethod(DataObjectMethodType.Select, false)]
BuildTools, public IEnumerable<BuildModel> SelectInVersionOrder()
{
var task = _buildCollection.Find(new BsonDocument())
.SortByDescending(b => b.MajorVersion)
.ThenByDescending(b => b.MinorVersion)
.ThenByDescending(b => b.Number)
.ThenByDescending(b => b.Revision)
.ThenByDescending(b => b.BuildTime)
.ToListAsync();
task.Wait();
return task.Result;
}
[Display(ResourceType = typeof(Model), Name = "Documentation")] [DataObjectMethod(DataObjectMethodType.Select, false)]
Documentation, public IEnumerable<BuildVersion> SelectBuildVersions()
{
var task = _buildCollection.DistinctAsync(b => new BuildVersion() { Major = b.MajorVersion, Minor = b.MinorVersion }, b => true);
task.Wait();
var outTask = task.Result.ToListAsync();
outTask.Wait();
return outTask.Result
.OrderByDescending(y => y.Major)
.ThenByDescending(y => y.Minor);
}
[Display(ResourceType = typeof(Model), Name = "Logging")] [DataObjectMethod(DataObjectMethodType.Select, false)]
Logging, public IEnumerable<int> SelectBuildYears()
{
var task = _buildCollection.DistinctAsync(b => b.BuildTime.Value.Year, b => b.BuildTime.HasValue);
task.Wait();
var outTask = task.Result.ToListAsync();
outTask.Wait();
return outTask.Result.OrderBy(b => b);
}
[Display(ResourceType = typeof(Model), Name = "PrivateLeak")] [DataObjectMethod(DataObjectMethodType.Select, false)]
PrivateLeak public IEnumerable<string> SelectBuildLabs()
} {
var task = _buildCollection.DistinctAsync(b => b.Lab.ToLower(), b => !string.IsNullOrWhiteSpace(b.Lab));
task.Wait();
var outTask = task.Result.ToListAsync();
outTask.Wait();
return outTask.Result.OrderBy(b => b);
}
public enum LevelOfFlight [DataObjectMethod(DataObjectMethodType.Select, false)]
{ public IEnumerable<string> SelectBuildLabs(byte major, byte minor)
[Display(ResourceType = typeof(Model), Name = "FlightNone")] {
None = 0, var task = _buildCollection.DistinctAsync(b => b.Lab.ToLower(), b => !string.IsNullOrWhiteSpace(b.Lab) && b.MajorVersion == major && b.MinorVersion == minor);
task.Wait();
var outTask = task.Result.ToListAsync();
outTask.Wait();
return outTask.Result.OrderBy(b => b);
}
[Display(ResourceType = typeof(Model), Name = "FlightLow")] [DataObjectMethod(DataObjectMethodType.Insert, true)]
Low = 1, public void Insert(BuildModel item)
{
item.Id = Guid.NewGuid();
var task = _buildCollection.InsertOneAsync(item);
task.Wait();
}
[Display(ResourceType = typeof(Model), Name = "FlightMedium")] [DataObjectMethod(DataObjectMethodType.Insert, false)]
Medium = 2, public void InsertAll(IEnumerable<BuildModel> items)
{
var task = _buildCollection.InsertManyAsync(items);
task.Wait();
}
[Display(ResourceType = typeof(Model), Name = "FlightHigh")] [DataObjectMethod(DataObjectMethodType.Update, true)]
High = 3 public void Update(BuildModel item)
} {
BuildModel old = SelectById(item.Id);
item.Added = old.Added;
item.Modified = DateTime.Now;
public struct BuildVersion var task = _buildCollection.ReplaceOneAsync(f => f.Id == item.Id, item);
{ task.Wait();
public byte Major { get; set; } }
public byte Minor { get; set; }
public override string ToString() [DataObjectMethod(DataObjectMethodType.Delete, true)]
{ public void DeleteById(Guid id)
return $"{Major}.{Minor}"; {
} var task = _buildCollection.DeleteOneAsync(f => f.Id == id);
} task.Wait();
}
}
public struct BuildGroup public enum TypeOfSource
{ {
public byte Major { get; set; } [Display(ResourceType = typeof(Model), Name = "PublicRelease")]
public byte Minor { get; set; } PublicRelease,
public ushort Build { get; set; }
public ushort? Revision { get; set; }
public override string ToString() [Display(ResourceType = typeof(Model), Name = "InternalLeak")]
{ InternalLeak,
return Revision.HasValue ?
$"{Major}.{Minor}.{Build}.{Revision.Value}" : [Display(ResourceType = typeof(Model), Name = "UpdateGDR")]
$"{Major}.{Minor}.{Build}"; UpdateGDR,
}
} [Display(ResourceType = typeof(Model), Name = "UpdateLDR")]
UpdateLDR,
[Display(ResourceType = typeof(Model), Name = "AppPackage")]
AppPackage,
[Display(ResourceType = typeof(Model), Name = "BuildTools")]
BuildTools,
[Display(ResourceType = typeof(Model), Name = "Documentation")]
Documentation,
[Display(ResourceType = typeof(Model), Name = "Logging")]
Logging,
[Display(ResourceType = typeof(Model), Name = "PrivateLeak")]
PrivateLeak
}
public enum LevelOfFlight
{
[Display(ResourceType = typeof(Model), Name = "FlightNone")]
None = 0,
[Display(ResourceType = typeof(Model), Name = "FlightLow")]
Low = 1,
[Display(ResourceType = typeof(Model), Name = "FlightMedium")]
Medium = 2,
[Display(ResourceType = typeof(Model), Name = "FlightHigh")]
High = 3
}
public struct BuildVersion
{
public byte Major { get; set; }
public byte Minor { get; set; }
public override string ToString()
{
return $"{Major}.{Minor}";
}
}
public class BuildGroup
{
public byte Major { get; set; }
public byte Minor { get; set; }
public ushort Build { get; set; }
public ushort? Revision { get; set; }
public override string ToString()
{
return Revision.HasValue ?
$"{Major}.{Minor}.{Build}.{Revision.Value}" :
$"{Major}.{Minor}.{Build}";
}
}
} }

View File

@ -1,4 +1,4 @@
@model BuildFeed.Models.Build @model BuildFeed.Models.BuildModel
@{ @{
ViewBag.Title = (string)(ViewContext.RouteData.Values["action"]) == "addBuild" ? string.Format("{0} | {1}", BuildFeed.Local.Front.AddABuild, BuildFeed.Local.Common.SiteName) : string.Format("{0} {1} | {2}", BuildFeed.Local.Front.EditBuild, Model.FullBuildString, BuildFeed.Local.Common.SiteName); ViewBag.Title = (string)(ViewContext.RouteData.Values["action"]) == "addBuild" ? string.Format("{0} | {1}", BuildFeed.Local.Front.AddABuild, BuildFeed.Local.Common.SiteName) : string.Format("{0} {1} | {2}", BuildFeed.Local.Front.EditBuild, Model.FullBuildString, BuildFeed.Local.Common.SiteName);
Html.EnableClientValidation(); Html.EnableClientValidation();

View File

@ -1,4 +1,4 @@
@model BuildFeed.Models.Build @model BuildFeed.Models.BuildModel
@{ @{
ViewBag.Title = Model.FullBuildString + " | BuildFeed"; ViewBag.Title = Model.FullBuildString + " | BuildFeed";

View File

@ -1,13 +1,13 @@
@model IGrouping<BuildFeed.Models.BuildGroup, BuildFeed.Models.Build> @model Tuple<BuildFeed.Models.BuildGroup, IEnumerable<BuildFeed.Models.BuildModel>>
@using Humanizer; @using Humanizer;
@{ @{
ViewBag.Title = string.Format("{0} | {1}", Model.Key.ToString(), BuildFeed.Local.Common.SiteName); ViewBag.Title = string.Format("{0} | {1}", Model.Item1.ToString(), BuildFeed.Local.Common.SiteName);
} }
<h1>@Model.Key.ToString()</h1> <h1>@Model.Item1.ToString()</h1>
<div class="row"> <div class="row">
@foreach (var build in Model.OrderBy(b => b.BuildTime)) @foreach (var build in Model.Item2)
{ {
<div class="col-sm-3 col-xs-6 build-group"> <div class="col-sm-3 col-xs-6 build-group">
<h3 class="build-group-title no-wrapping" title="@build.Lab"><a href="@Url.Action("viewBuild", new {id = build.Id})">@build.Lab</a></h3> <h3 class="build-group-title no-wrapping" title="@build.Lab"><a href="@Url.Action("viewBuild", new {id = build.Id})">@build.Lab</a></h3>

View File

@ -1,4 +1,4 @@
@model IEnumerable<BuildFeed.Models.Build> @model IEnumerable<BuildFeed.Models.BuildModel>
@using Humanizer; @using Humanizer;
@{ @{
ViewBag.Title = string.Format("{0} {1}{2} | {3}", BuildFeed.Local.Front.BuildsFrom, ViewBag.ItemId, ViewBag.PageNumber == 1 ? "" : string.Format(BuildFeed.Local.Common.PageTitleSegment, ViewBag.PageNumber), BuildFeed.Local.Common.SiteName); ViewBag.Title = string.Format("{0} {1}{2} | {3}", BuildFeed.Local.Front.BuildsFrom, ViewBag.ItemId, ViewBag.PageNumber == 1 ? "" : string.Format(BuildFeed.Local.Common.PageTitleSegment, ViewBag.PageNumber), BuildFeed.Local.Common.SiteName);

View File

@ -1,4 +1,4 @@
@model IEnumerable<BuildFeed.Models.Build> @model IEnumerable<BuildFeed.Models.BuildModel>
@using Humanizer; @using Humanizer;
@{ @{
ViewBag.Title = string.Format("{0}{1} | {2}", ViewBag.ItemId, ViewBag.PageNumber == 1 ? "" : string.Format(BuildFeed.Local.Common.PageTitleSegment, ViewBag.PageNumber), @BuildFeed.Local.Common.SiteName); ViewBag.Title = string.Format("{0}{1} | {2}", ViewBag.ItemId, ViewBag.PageNumber == 1 ? "" : string.Format(BuildFeed.Local.Common.PageTitleSegment, ViewBag.PageNumber), @BuildFeed.Local.Common.SiteName);

View File

@ -1,4 +1,4 @@
@model IEnumerable<BuildFeed.Models.Build> @model IEnumerable<BuildFeed.Models.BuildModel>
@using Humanizer; @using Humanizer;
@{ @{
ViewBag.Title = string.Format("{0} {1}{2} | {3}", BuildFeed.Local.Common.ProductName, ViewBag.ItemId, ViewBag.PageNumber == 1 ? "" : string.Format(BuildFeed.Local.Common.PageTitleSegment, ViewBag.PageNumber), BuildFeed.Local.Common.SiteName); ViewBag.Title = string.Format("{0} {1}{2} | {3}", BuildFeed.Local.Common.ProductName, ViewBag.ItemId, ViewBag.PageNumber == 1 ? "" : string.Format(BuildFeed.Local.Common.PageTitleSegment, ViewBag.PageNumber), BuildFeed.Local.Common.SiteName);

View File

@ -1,4 +1,4 @@
@model IEnumerable<BuildFeed.Models.Build> @model IEnumerable<BuildFeed.Models.BuildModel>
@using Humanizer; @using Humanizer;
@{ @{
ViewBag.Title = string.Format("{0} {1}{2} | {3}", BuildFeed.Local.Front.BuildsFrom, ViewBag.ItemId, ViewBag.PageNumber == 1 ? "" : string.Format(BuildFeed.Local.Common.PageTitleSegment, ViewBag.PageNumber), BuildFeed.Local.Common.SiteName); ViewBag.Title = string.Format("{0} {1}{2} | {3}", BuildFeed.Local.Front.BuildsFrom, ViewBag.ItemId, ViewBag.PageNumber == 1 ? "" : string.Format(BuildFeed.Local.Common.PageTitleSegment, ViewBag.PageNumber), BuildFeed.Local.Common.SiteName);

View File

@ -10,11 +10,8 @@
<add key="PreserveLoginUrl" value="true" /> <add key="PreserveLoginUrl" value="true" />
<add key="ClientValidationEnabled" value="true" /> <add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" /> <add key="UnobtrusiveJavaScriptEnabled" value="true" />
<add key="data:ServerHost" value="localhost" />
<add key="data:ServerPort" value="6379" />
<add key="data:ServerDB" value="1" />
<add key="data:MongoDB" value="BuildFeed" /> <add key="data:MongoDB" value="BuildFeed" />
<add key="RouteDebugger:Enabled" value="false" /> <add key="RouteDebugger:Enabled" value="true" />
</appSettings> </appSettings>
<system.web> <system.web>
<compilation debug="true" targetFramework="4.6" /> <compilation debug="true" targetFramework="4.6" />

View File

@ -125,7 +125,17 @@ label, .control-label, .help-block, .checkbox, .radio
white-space: nowrap; white-space: nowrap;
} }
#search-results .list-group-item-heading h4 #search-results .list-group-item-heading h4
{ {
font-size: 16px; font-size: 16px;
} }
#haackroutedebugger
{
color: #000;
}
#haackroutedebugger h1, #haackroutedebugger h2, #haackroutedebugger h3
{
text-shadow: none;
}

View File

@ -0,0 +1,29 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace RedisMongoMigration
{
public enum TypeOfSource
{
PublicRelease,
InternalLeak,
UpdateGDR,
UpdateLDR,
AppPackage,
BuildTools,
Documentation,
Logging,
PrivateLeak
}
public enum LevelOfFlight
{
None = 0,
Low = 1,
Medium = 2,
High = 3
}
}

View File

@ -0,0 +1,110 @@
using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;
using MongoDB.Driver;
using System;
using System.Collections.Generic;
using System.Text;
namespace RedisMongoMigration.Mongo
{
public class BuildModel
{
[BsonId]
public Guid Id { get; set; }
public long? LegacyId { get; set; }
public byte MajorVersion { get; set; }
public byte MinorVersion { get; set; }
public ushort Number { get; set; }
public ushort? Revision { get; set; }
public string Lab { get; set; }
public DateTime? BuildTime { get; set; }
public DateTime Added { get; set; }
public DateTime Modified { get; set; }
public TypeOfSource SourceType { get; set; }
public string SourceDetails { get; set; }
public DateTime? LeakDate { get; set; }
public LevelOfFlight FlightLevel { get; set; }
public bool IsLeaked
{
get
{
switch (SourceType)
{
case TypeOfSource.PublicRelease:
case TypeOfSource.InternalLeak:
case TypeOfSource.UpdateGDR:
case TypeOfSource.UpdateLDR:
return true;
default:
return false;
}
}
}
public string FullBuildString
{
get
{
StringBuilder sb = new StringBuilder();
sb.AppendFormat("{0}.{1}.{2}", MajorVersion, MinorVersion, Number);
if (Revision.HasValue)
{
sb.AppendFormat(".{0}", Revision);
}
if (!string.IsNullOrWhiteSpace(Lab))
{
sb.AppendFormat(".{0}", Lab);
}
if (BuildTime.HasValue)
{
sb.AppendFormat(".{0:yyMMdd-HHmm}", BuildTime);
}
return sb.ToString();
}
}
}
public class Build
{
private const string _buildCollectionName = "builds";
private MongoClient _dbClient;
private IMongoCollection<BuildModel> _buildCollection;
public Build()
{
_dbClient = new MongoClient(new MongoClientSettings()
{
Server = new MongoServerAddress("localhost", 27017)
});
_buildCollection = _dbClient.GetDatabase("BuildFeed").GetCollection<BuildModel>(_buildCollectionName);
}
public List<BuildModel> Select()
{
var task = _buildCollection.Find(new BsonDocument()).ToListAsync();
task.Wait();
return task.Result;
}
public void Insert(BuildModel item)
{
item.Id = Guid.NewGuid();
var task = _buildCollection.InsertOneAsync(item);
task.Wait();
}
public void InsertAll(IEnumerable<BuildModel> items)
{
var task = _buildCollection.InsertManyAsync(items);
task.Wait();
}
}
}

View File

@ -4,12 +4,41 @@
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using MBuildModel = RedisMongoMigration.Mongo.BuildModel;
using MBuild = RedisMongoMigration.Mongo.Build;
using RBuild = RedisMongoMigration.Redis.Build;
namespace RedisMongoMigration namespace RedisMongoMigration
{ {
class Program class Program
{ {
static void Main(string[] args) static void Main(string[] args)
{ {
} var builds = RBuild.Select();
} var newBuilds = from b in builds
select new MBuildModel()
{
Id = Guid.NewGuid(),
LegacyId = b.Id,
MajorVersion = b.MajorVersion,
MinorVersion = b.MinorVersion,
Number = b.Number,
Revision = b.Revision,
Lab = b.Lab,
BuildTime = b.BuildTime,
Added = b.Added,
Modified = b.Modified,
SourceType = b.SourceType,
SourceDetails = b.SourceDetails,
LeakDate = b.LeakDate,
FlightLevel = b.FlightLevel
};
MBuild m = new MBuild();
m.InsertAll(newBuilds);
Console.WriteLine("Builds: Complete");
Console.ReadKey();
}
}
} }

View File

@ -1,6 +1,8 @@
using NServiceKit.DataAnnotations; using NServiceKit.DataAnnotations;
using NServiceKit.DesignPatterns.Model; using NServiceKit.DesignPatterns.Model;
using NServiceKit.Redis;
using System; using System;
using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.Text; using System.Text;
@ -14,30 +16,18 @@ public class Build : IHasId<long>
[AutoIncrement] [AutoIncrement]
[Index] [Index]
public long Id { get; set; } public long Id { get; set; }
public byte MajorVersion { get; set; } public byte MajorVersion { get; set; }
public byte MinorVersion { get; set; } public byte MinorVersion { get; set; }
public ushort Number { get; set; } public ushort Number { get; set; }
public ushort? Revision { get; set; } public ushort? Revision { get; set; }
public string Lab { get; set; } public string Lab { get; set; }
public DateTime? BuildTime { get; set; } public DateTime? BuildTime { get; set; }
public DateTime Added { get; set; } public DateTime Added { get; set; }
public DateTime Modified { get; set; } public DateTime Modified { get; set; }
public TypeOfSource SourceType { get; set; } public TypeOfSource SourceType { get; set; }
public string SourceDetails { get; set; } public string SourceDetails { get; set; }
public DateTime? LeakDate { get; set; } public DateTime? LeakDate { get; set; }
public LevelOfFlight FlightLevel { get; set; } public LevelOfFlight FlightLevel { get; set; }
public bool IsLeaked public bool IsLeaked
@ -80,53 +70,15 @@ public string FullBuildString
return sb.ToString(); return sb.ToString();
} }
} }
}
public enum TypeOfSource public static IEnumerable<Build> Select()
{ {
PublicRelease, using (RedisClient rClient = new RedisClient("localhost", 6379, db: 1))
InternalLeak, {
UpdateGDR, var client = rClient.As<Build>();
UpdateLDR, return client.GetAll();
AppPackage, }
BuildTools, }
Documentation, }
Logging,
PrivateLeak
}
public enum LevelOfFlight
{
None = 0,
Low = 1,
Medium = 2,
High = 3
}
public struct BuildVersion
{
public byte Major { get; set; }
public byte Minor { get; set; }
public override string ToString()
{
return $"{Major}.{Minor}";
}
}
public struct BuildGroup
{
public byte Major { get; set; }
public byte Minor { get; set; }
public ushort Build { get; set; }
public ushort? Revision { get; set; }
public override string ToString()
{
return Revision.HasValue ?
$"{Major}.{Minor}.{Build}.{Revision.Value}" :
$"{Major}.{Minor}.{Build}";
}
}
} }

View File

@ -33,6 +33,18 @@
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="MongoDB.Bson, Version=2.0.1.27, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\MongoDB.Bson.2.0.1\lib\net45\MongoDB.Bson.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="MongoDB.Driver, Version=2.0.1.27, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\MongoDB.Driver.2.0.1\lib\net45\MongoDB.Driver.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="MongoDB.Driver.Core, Version=2.0.1.27, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\MongoDB.Driver.Core.2.0.1\lib\net45\MongoDB.Driver.Core.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="NServiceKit.Common, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL"> <Reference Include="NServiceKit.Common, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\NServiceKit.Common.1.0.31\lib\net35\NServiceKit.Common.dll</HintPath> <HintPath>..\packages\NServiceKit.Common.1.0.31\lib\net35\NServiceKit.Common.dll</HintPath>
<Private>True</Private> <Private>True</Private>
@ -60,6 +72,8 @@
<Reference Include="System.Xml" /> <Reference Include="System.Xml" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Build.cs" />
<Compile Include="Mongo\Build.cs" />
<Compile Include="Program.cs" /> <Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Redis\Build.cs" /> <Compile Include="Redis\Build.cs" />
@ -71,6 +85,7 @@
<None Include="App.config" /> <None Include="App.config" />
<None Include="packages.config" /> <None Include="packages.config" />
</ItemGroup> </ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets. Other similar extension points exist, see Microsoft.Common.targets.

View File

@ -1,5 +1,8 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<packages> <packages>
<package id="MongoDB.Bson" version="2.0.1" targetFramework="net46" />
<package id="MongoDB.Driver" version="2.0.1" targetFramework="net46" />
<package id="MongoDB.Driver.Core" version="2.0.1" targetFramework="net46" />
<package id="NServiceKit.Common" version="1.0.31" targetFramework="net46" /> <package id="NServiceKit.Common" version="1.0.31" targetFramework="net46" />
<package id="NServiceKit.Redis" version="1.0.16" targetFramework="net46" /> <package id="NServiceKit.Redis" version="1.0.16" targetFramework="net46" />
<package id="NServiceKit.Text" version="1.0.10" targetFramework="net46" /> <package id="NServiceKit.Text" version="1.0.10" targetFramework="net46" />