// Note: setAssignedId is currently not exposed as an option // -- waiting for Adapter refactoring LVL 04 to expose a new CRUDconfig input for the Push // CRUDconfig will become available to all CRUD methods protected bool CreateAnyObject(List <IObject> objects, bool setAssignedId = true) { /// Create the objects List <SpeckleObject> objs_serialized = SpeckleCore.Converter.Serialise(objects); SpeckleLayer.ObjectCount += objects.Count(); SpeckleStream.Objects.AddRange(objs_serialized); /// Assign any other property to the objects before sending them var objList = objects.ToList(); int i = 0; foreach (var o in SpeckleStream.Objects) { IBHoMObject bhomObj = objList[i] as IBHoMObject; if (bhomObj != null) { SpeckleStream.Objects[i].Name = string.IsNullOrEmpty(bhomObj.Name) ? bhomObj.GetType().ToString() : bhomObj.Name; //SpeckleStream.Objects[i].Type = string.IsNullOrEmpty(bhomObj.Name) ? bhomObj.GetType().ToString() : bhomObj.Name; } i++; } /// Send the objects var updateResponse = SpeckleClient.StreamUpdateAsync(SpeckleStreamId, SpeckleStream).Result; SpeckleClient.BroadcastMessage("stream", SpeckleStreamId, new { eventType = "update-global" }); /// Read the IBHoMobjects as exported in speckle /// so we can assign the Speckle-generated id into the BHoMobjects if (setAssignedId) { ResponseObject response = SpeckleClient.StreamGetObjectsAsync(SpeckleStreamId, "").Result; List <IBHoMObject> bHoMObjects_inSpeckle = new List <IBHoMObject>(); IEnumerable <IBHoMObject> iBhomObjsInSpeckle = BH.Engine.Speckle.Convert.ToBHoM(response, true); VennDiagram <IBHoMObject> correspondenceDiagram = Engine.Data.Create.VennDiagram(objects.Where(o => o as IBHoMObject != null).Cast <IBHoMObject>(), iBhomObjsInSpeckle, new IBHoMGUIDComparer()); if (correspondenceDiagram.Intersection.Count != objects.Count()) { var gna = 0; //Engine.Reflection.Compute.RecordError("Push failed.\nNumber of objects created in Speckle do not correspond to the number of objects pushed."); //return false; } correspondenceDiagram.Intersection.ForEach(o => o.Item1.CustomData[AdapterId] = o.Item2.CustomData[AdapterId]); } return(true); }
public override List <object> Push(IEnumerable <object> objects, string tag = "", PushType pushType = PushType.AdapterDefault, ActionConfig actionConfig = null) { // Clone objects for immutability in the UI List <object> objectsToPush = objects.Select(x => x.DeepClone()).ToList(); // Initialize the SpeckleStream SpeckleClient.Stream.Objects = new List <SpeckleObject>(); // stream is immutable // //- Read config SpecklePushConfig pushConfig = (actionConfig as SpecklePushConfig) ?? new SpecklePushConfig(); // //- Use "Speckle" history: produces a new stream at every push that corresponds to the old version. Enabled by default. if (pushConfig.EnableHistory) { SetupHistory(); } // Actual creation and add to the stream for (int i = 0; i < objectsToPush.Count(); i++) { SpeckleObject speckleObject = ToSpeckle(objectsToPush[i] as dynamic, pushConfig); // Dynamic dispatch to most appropriate method // Add objects to the stream SpeckleClient.Stream.Objects.Add(speckleObject); } // // - Send the objects try { // Try the batch upload BatchUpdateStream(pushConfig); } catch (Exception e) { try { // If the batch upload fails, try the standard SpeckleCore Update as a last resort. //// - Issue: with `StreamUpdateAsync` Speckle doesn't seem to send anything if the Stream is initially empty. //// - You need to Push twice if the Stream is initially empty. var updateResponse = SpeckleClient.StreamUpdateAsync(SpeckleClient.Stream.StreamId, SpeckleClient.Stream).Result; SpeckleClient.BroadcastMessage("stream", SpeckleClient.Stream.StreamId, new { eventType = "update-global" }); } catch { // If all has failed, return the first error. BH.Engine.Reflection.Compute.RecordError($"Upload to Speckle failed. Message returned:\n{e.InnerException.Message}"); return(new List <object>()); } } return(objectsToPush); }
protected bool CreateIObjects(IEnumerable <IObject> objects) { IEnumerable <object> newObjects = (IEnumerable <object>)objects; //hacky; assumes T is always a reference type. Should be no problem anyway List <SpeckleObject> objs_serialized = SpeckleCore.Converter.Serialise(newObjects); SpeckleLayer.ObjectCount += objects.Count(); SpeckleStream.Objects.AddRange(objs_serialized); var updateResponse = SpeckleClient.StreamUpdateAsync(SpeckleStreamId, SpeckleStream).Result; SpeckleClient.BroadcastMessage("stream", SpeckleStreamId, new { eventType = "update-global" }); return(true); }
public void BatchUpdateStream(SpecklePushConfig pushConfig) { List <SpeckleObject> convertedObjects = SpeckleClient.Stream.Objects; SpeckleCore.SpeckleInitializer.Initialize(); SpeckleCore.LocalContext.Init(); LocalContext.PruneExistingObjects(convertedObjects, SpeckleClient.BaseUrl); List <SpeckleObject> persistedObjects = new List <SpeckleObject>(); OrderedDictionary JobQueue = new OrderedDictionary(); if (convertedObjects.Count(obj => obj.Type == "Placeholder") != convertedObjects.Count) { // create the update payloads int count = 0; var objectUpdatePayloads = new List <List <SpeckleObject> >(); long totalBucketSize = 0; long currentBucketSize = 0; var currentBucketObjects = new List <SpeckleObject>(); var allObjects = new List <SpeckleObject>(); foreach (SpeckleObject convertedObject in convertedObjects) { if (count++ % 100 == 0) { //Message = "Converted " + count + " objects out of " + convertedObjects.Count() + "."; } // size checking & bulk object creation payloads creation long size = Converter.getBytes(convertedObject).Length; currentBucketSize += size; totalBucketSize += size; currentBucketObjects.Add(convertedObject); // Object is too big? if (size > 2e6) { BH.Engine.Reflection.Compute.RecordWarning("An object is too big for the current Speckle limitations."); currentBucketObjects.Remove(convertedObject); } if (currentBucketSize > 3e5) // restrict max to ~300kb; { //BH.Engine.Reflection.Compute.RecordNote("Reached payload limit. Making a new one, current #: " + objectUpdatePayloads.Count); objectUpdatePayloads.Add(currentBucketObjects); currentBucketObjects = new List <SpeckleObject>(); currentBucketSize = 0; } } // add in the last bucket if (currentBucketObjects.Count > 0) { objectUpdatePayloads.Add(currentBucketObjects); } if (objectUpdatePayloads.Count > 1) { BH.Engine.Reflection.Compute.RecordNote($"Payload has been split in { objectUpdatePayloads.Count } batches. Total size is {totalBucketSize / 1024} kB."); } // create bulk object creation tasks List <ResponseObject> responses = new List <ResponseObject>(); foreach (var payload in objectUpdatePayloads) { //Message = String.Format("{0}/{1}", k++, objectUpdatePayloads.Count); try { var objResponse = SpeckleClient.ObjectCreateAsync(payload).Result; responses.Add(objResponse); persistedObjects.AddRange(objResponse.Resources); int m = 0; foreach (var oL in payload) { oL._id = objResponse.Resources[m++]._id; } // push sent objects in the cache non-blocking Task.Run(() => { foreach (var oL in payload) { if (oL.Type != "Placeholder") { LocalContext.AddSentObject(oL, SpeckleClient.BaseUrl); } } }); } catch (Exception err) { BH.Engine.Reflection.Compute.RecordWarning(err.Message); continue; } } } else { persistedObjects = convertedObjects; } // create placeholders for stream update payload List <SpeckleObject> placeholders = new List <SpeckleObject>(); //foreach ( var myResponse in responses ) foreach (var obj in persistedObjects) { placeholders.Add(new SpecklePlaceholder() { _id = obj._id }); } SpeckleClient.Stream.Objects = placeholders; // set some base properties (will be overwritten) var baseProps = new Dictionary <string, object>(); baseProps["units"] = "m"; baseProps["tolerance"] = "0.001"; baseProps["angleTolerance"] = "0.01"; SpeckleClient.Stream.BaseProperties = baseProps; var response = SpeckleClient.StreamUpdateAsync(SpeckleClient.StreamId, SpeckleClient.Stream).Result; SpeckleClient.BroadcastMessage("stream", SpeckleClient.StreamId, new { eventType = "update-global" }); }