Esempio n. 1
0
        private byte[] EncodeOffsetRequest(OffsetRequest request)
        {
            var message = new WriteByteStream();

            if (request.Offsets == null)
            {
                request.Offsets = new List <Offset>();
            }

            message.Pack(EncodeHeader(request));

            var topicGroups = request.Offsets.GroupBy(x => x.Topic).ToList();

            message.Pack(ReplicaId.ToBytes(), topicGroups.Count.ToBytes());

            foreach (var topicGroup in topicGroups)
            {
                var partitions = topicGroup.GroupBy(x => x.PartitionId).ToList();
                message.Pack(topicGroup.Key.ToInt16SizedBytes(), partitions.Count.ToBytes());

                foreach (var partition in partitions)
                {
                    foreach (var offset in partition)
                    {
                        message.Pack(partition.Key.ToBytes(), offset.Time.ToBytes(), offset.MaxOffsets.ToBytes());
                    }
                }
            }

            message.Prepend(message.Length().ToBytes());

            return(message.Payload());
        }
Esempio n. 2
0
 public JsonRow(string streamId, ReplicaId replicaId, VClock timestamp, string jsonPayload)
 {
     StreamId    = streamId;
     ReplicaId   = replicaId;
     Timestamp   = timestamp;
     JsonPayload = jsonPayload;
 }
        /// <inheritdoc />
        public Task <ReplicaInfo> GetReplicaInfoAsync(
            PartitionId partitionId,
            ReplicaId replicaId,
            long?serverTimeout = 60,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            partitionId.ThrowIfNull(nameof(partitionId));
            replicaId.ThrowIfNull(nameof(replicaId));
            serverTimeout?.ThrowIfOutOfInclusiveRange("serverTimeout", 1, 4294967295);
            var requestId = Guid.NewGuid().ToString();
            var url       = "Partitions/{partitionId}/$/GetReplicas/{replicaId}";

            url = url.Replace("{partitionId}", partitionId.ToString());
            url = url.Replace("{replicaId}", replicaId.ToString());
            var queryParams = new List <string>();

            // Append to queryParams if not null.
            serverTimeout?.AddToQueryParameters(queryParams, $"timeout={serverTimeout}");
            queryParams.Add("api-version=6.0");
            url += "?" + string.Join("&", queryParams);

            HttpRequestMessage RequestFunc()
            {
                var request = new HttpRequestMessage()
                {
                    Method = HttpMethod.Get,
                };

                return(request);
            }

            return(this.httpClient.SendAsyncGetResponse(RequestFunc, url, ReplicaInfoConverter.Deserialize, requestId, cancellationToken));
        }
Esempio n. 4
0
 public PayloadRow(string streamId, ReplicaId replicaId, VClock timestamp, int serializerId, byte[] payload)
 {
     StreamId     = streamId;
     ReplicaId    = replicaId;
     Timestamp    = timestamp;
     SerializerId = serializerId;
     Payload      = payload;
 }
Esempio n. 5
0
        void OnPossessPawn(BitStream bs)
        {
            var replicaId = bs.ReadReplicaId();
            var pawnIdx   = bs.ReadByte();

            currentReplicaPossess = replicaId;
            pawnIdxToPossess      = pawnIdx;
        }
Esempio n. 6
0
        /// <summary>
        /// Increments a logical time value for a target <paramref name="replicaId"/>,
        /// returning new instance of <see cref="VClock"/> in the result.
        /// </summary>
        public VClock Increment(ReplicaId replicaId)
        {
            long time;

            return(Value != null && Value.TryGetValue(replicaId, out time)
                ? new VClock(Value.SetItem(replicaId, time + 1))
                : new VClock((Value ?? ImmutableDictionary <ReplicaId, long> .Empty).SetItem(replicaId, 1L)));
        }
Esempio n. 7
0
        /// <summary>
        /// Returns a new instance of the <see cref="VClock"/> containing
        /// only information about target <paramref name="replicaId"/>.
        /// </summary>
        public VClock CopyOne(ReplicaId replicaId)
        {
            long time;

            return(Value != null && Value.TryGetValue(replicaId, out time)
                ? new VClock(ImmutableDictionary.CreateRange(new[] { new KeyValuePair <ReplicaId, long>(replicaId, time) }))
                : new VClock(ImmutableDictionary <ReplicaId, long> .Empty));
        }
Esempio n. 8
0
        public PendingAck(ReplicaId target, Versioned <T> versioned, DateTime timestamp, ImmutableHashSet <ReplicaId> members)
        {
            Target    = target;
            Versioned = versioned;
            Timestamp = timestamp;
            Members   = members;

            hashCode = HashCode();
        }
Esempio n. 9
0
        void OnDisconnected(string reason)
        {
            Debug.Log("[Client] <b>Disconnected</b> (" + reason + ")");

            // Cleanup
            currentReplicaPossess = ReplicaId.Invalid;

            Client.replicaManager.Reset();

            if (sceneHandle.IsValid())
            {
                Addressables.UnloadSceneAsync(sceneHandle);
            }
        }
Esempio n. 10
0
        public override int GetHashCode()
        {
            int hash = 1;

            if (ReplicaId.Length != 0)
            {
                hash ^= ReplicaId.GetHashCode();
            }
            if (Result != 0)
            {
                hash ^= Result.GetHashCode();
            }
            return(hash);
        }
        /// <inheritdoc />
        public Task <ReplicaHealth> GetReplicaHealthUsingPolicyAsync(
            PartitionId partitionId,
            ReplicaId replicaId,
            int?eventsHealthStateFilter = 0,
            ApplicationHealthPolicy applicationHealthPolicy = default(ApplicationHealthPolicy),
            long?serverTimeout = 60,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            partitionId.ThrowIfNull(nameof(partitionId));
            replicaId.ThrowIfNull(nameof(replicaId));
            serverTimeout?.ThrowIfOutOfInclusiveRange("serverTimeout", 1, 4294967295);
            var requestId = Guid.NewGuid().ToString();
            var url       = "Partitions/{partitionId}/$/GetReplicas/{replicaId}/$/GetHealth";

            url = url.Replace("{partitionId}", partitionId.ToString());
            url = url.Replace("{replicaId}", replicaId.ToString());
            var queryParams = new List <string>();

            // Append to queryParams if not null.
            eventsHealthStateFilter?.AddToQueryParameters(queryParams, $"EventsHealthStateFilter={eventsHealthStateFilter}");
            serverTimeout?.AddToQueryParameters(queryParams, $"timeout={serverTimeout}");
            queryParams.Add("api-version=6.0");
            url += "?" + string.Join("&", queryParams);

            string content;

            using (var sw = new StringWriter())
            {
                if (applicationHealthPolicy != default(ApplicationHealthPolicy))
                {
                    ApplicationHealthPolicyConverter.Serialize(new JsonTextWriter(sw), applicationHealthPolicy);
                }

                content = sw.ToString();
            }

            HttpRequestMessage RequestFunc()
            {
                var request = new HttpRequestMessage()
                {
                    Method  = HttpMethod.Post,
                    Content = new StringContent(content, Encoding.UTF8),
                };

                request.Content.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse("application/json; charset=utf-8");
                return(request);
            }

            return(this.httpClient.SendAsyncGetResponse(RequestFunc, url, ReplicaHealthConverter.Deserialize, requestId, cancellationToken));
        }
        /// <inheritdoc />
        public Task ReportReplicaHealthAsync(
            PartitionId partitionId,
            ReplicaId replicaId,
            ReplicaHealthReportServiceKind?replicaHealthReportServiceKind,
            HealthInformation healthInformation,
            bool?immediate     = false,
            long?serverTimeout = 60,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            partitionId.ThrowIfNull(nameof(partitionId));
            replicaId.ThrowIfNull(nameof(replicaId));
            replicaHealthReportServiceKind.ThrowIfNull(nameof(replicaHealthReportServiceKind));
            healthInformation.ThrowIfNull(nameof(healthInformation));
            serverTimeout?.ThrowIfOutOfInclusiveRange("serverTimeout", 1, 4294967295);
            var requestId = Guid.NewGuid().ToString();
            var url       = "Partitions/{partitionId}/$/GetReplicas/{replicaId}/$/ReportHealth";

            url = url.Replace("{partitionId}", partitionId.ToString());
            url = url.Replace("{replicaId}", replicaId.ToString());
            var queryParams = new List <string>();

            // Append to queryParams if not null.
            replicaHealthReportServiceKind?.AddToQueryParameters(queryParams, $"ReplicaHealthReportServiceKind={replicaHealthReportServiceKind.ToString()}");
            immediate?.AddToQueryParameters(queryParams, $"Immediate={immediate}");
            serverTimeout?.AddToQueryParameters(queryParams, $"timeout={serverTimeout}");
            queryParams.Add("api-version=6.0");
            url += "?" + string.Join("&", queryParams);

            string content;

            using (var sw = new StringWriter())
            {
                HealthInformationConverter.Serialize(new JsonTextWriter(sw), healthInformation);
                content = sw.ToString();
            }

            HttpRequestMessage RequestFunc()
            {
                var request = new HttpRequestMessage()
                {
                    Method  = HttpMethod.Post,
                    Content = new StringContent(content, Encoding.UTF8),
                };

                request.Content.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse("application/json; charset=utf-8");
                return(request);
            }

            return(this.httpClient.SendAsync(RequestFunc, url, requestId, cancellationToken));
        }
Esempio n. 13
0
        /// <inheritdoc />
        public Task <IEnumerable <ReplicaEvent> > GetPartitionReplicaEventListAsync(
            PartitionId partitionId,
            ReplicaId replicaId,
            string startTimeUtc,
            string endTimeUtc,
            long?serverTimeout                  = 60,
            string eventsTypesFilter            = default(string),
            bool?excludeAnalysisEvents          = default(bool?),
            bool?skipCorrelationLookup          = default(bool?),
            CancellationToken cancellationToken = default(CancellationToken))
        {
            partitionId.ThrowIfNull(nameof(partitionId));
            replicaId.ThrowIfNull(nameof(replicaId));
            startTimeUtc.ThrowIfNull(nameof(startTimeUtc));
            endTimeUtc.ThrowIfNull(nameof(endTimeUtc));
            serverTimeout?.ThrowIfOutOfInclusiveRange("serverTimeout", 1, 4294967295);
            var requestId = Guid.NewGuid().ToString();
            var url       = "EventsStore/Partitions/{partitionId}/$/Replicas/{replicaId}/$/Events";

            url = url.Replace("{partitionId}", partitionId.ToString());
            url = url.Replace("{replicaId}", replicaId.ToString());
            var queryParams = new List <string>();

            // Append to queryParams if not null.
            serverTimeout?.AddToQueryParameters(queryParams, $"timeout={serverTimeout}");
            startTimeUtc?.AddToQueryParameters(queryParams, $"StartTimeUtc={startTimeUtc}");
            endTimeUtc?.AddToQueryParameters(queryParams, $"EndTimeUtc={endTimeUtc}");
            eventsTypesFilter?.AddToQueryParameters(queryParams, $"EventsTypesFilter={eventsTypesFilter}");
            excludeAnalysisEvents?.AddToQueryParameters(queryParams, $"ExcludeAnalysisEvents={excludeAnalysisEvents}");
            skipCorrelationLookup?.AddToQueryParameters(queryParams, $"SkipCorrelationLookup={skipCorrelationLookup}");
            queryParams.Add("api-version=6.4");
            url += "?" + string.Join("&", queryParams);

            HttpRequestMessage RequestFunc()
            {
                var request = new HttpRequestMessage()
                {
                    Method = HttpMethod.Get,
                };

                return(request);
            }

            return(this.httpClient.SendAsyncGetResponseAsList(RequestFunc, url, ReplicaEventConverter.Deserialize, requestId, cancellationToken));
        }
        /// <inheritdoc />
        public Task RemoveReplicaAsync(
            NodeName nodeName,
            PartitionId partitionId,
            ReplicaId replicaId,
            bool?forceRemove   = default(bool?),
            long?serverTimeout = 60,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            nodeName.ThrowIfNull(nameof(nodeName));
            partitionId.ThrowIfNull(nameof(partitionId));
            replicaId.ThrowIfNull(nameof(replicaId));
            serverTimeout?.ThrowIfOutOfInclusiveRange("serverTimeout", 1, 4294967295);
            var requestId = Guid.NewGuid().ToString();
            var url       = "Nodes/{nodeName}/$/GetPartitions/{partitionId}/$/GetReplicas/{replicaId}/$/Delete";

            url = url.Replace("{nodeName}", Uri.EscapeDataString(nodeName.ToString()));
            url = url.Replace("{partitionId}", partitionId.ToString());
            url = url.Replace("{replicaId}", replicaId.ToString());
            var queryParams = new List <string>();

            // Append to queryParams if not null.
            forceRemove?.AddToQueryParameters(queryParams, $"ForceRemove={forceRemove}");
            serverTimeout?.AddToQueryParameters(queryParams, $"timeout={serverTimeout}");
            queryParams.Add("api-version=6.0");
            url += "?" + string.Join("&", queryParams);

            HttpRequestMessage RequestFunc()
            {
                var request = new HttpRequestMessage()
                {
                    Method = HttpMethod.Post,
                };

                return(request);
            }

            return(this.httpClient.SendAsync(RequestFunc, url, requestId, cancellationToken));
        }
Esempio n. 15
0
        public void TestStatic()
        {
            // Setup
            var masterSystem = CreateSystem();
            var master       = masterSystem.CreateStreamWriter();
            var slaveSystem  = CreateSystem();

            bool slaveReplicaAdded = false;

            slaveSystem.ReplicaAdded += x => slaveReplicaAdded = true;

            // Add
            ReplicaId id = 10;

            masterSystem.AddStaticReplica(id, new Protobuf.TestObject()
            {
                Name = "A"
            }, StaticReplicaOptions.DefaultMaster);
            slaveSystem.AddStaticReplica(id, new Protobuf.TestObject()
            {
                Name = "A"
            }, StaticReplicaOptions.DefaultSlave);

            slaveReplicaAdded = false;
            master.WriteTo(slaveSystem);
            Assert.IsFalse(slaveReplicaAdded);

            // Update
            masterSystem.UpdateReplica(id, new Protobuf.TestObject()
            {
                State = 2
            });
            master.WriteTo(slaveSystem);

            Assert.AreEqual(slaveSystem.GetReplica <Protobuf.TestObject>(id).State, 2);
        }
Esempio n. 16
0
 public VClock SetTime(ReplicaId replicaId, long localTime) =>
 new VClock((Value ?? ImmutableDictionary <ReplicaId, long> .Empty).SetItem(replicaId, localTime));
Esempio n. 17
0
 /// <summary>
 /// Creates a new instance of a <see cref="VClock"/> with <paramref name="value"/> set for target replica.
 /// </summary>
 public static VClock Create(ReplicaId replicaId, long value = 1L) =>
 new VClock(new KeyValuePair <ReplicaId, long>(replicaId, value));
Esempio n. 18
0
 public Send(ReplicaId origin, ReplicaId lastSeenBy, Versioned <T> versioned)
 {
     Origin     = origin;
     LastSeenBy = lastSeenBy;
     Versioned  = versioned;
 }
Esempio n. 19
0
        public ReplicatorActor(ReplicaId myself, ReplicatorSettings settings)
        {
            this.myself            = myself;
            this.settings          = settings;
            replicatorRelativePath = Self.Path.ToStringWithoutAddress();

            Receive <ClusterEvent.MemberUp>(up =>
            {
                if (HasRole(up.Member) && up.Member.Address != cluster.SelfAddress)
                {
                    // send invitation to a new member
                    var path = up.Member.Address.ToString() + replicatorRelativePath;
                    Context.ActorSelection(path).Tell(new Invitation(myself, Self));
                }
            });
            Receive <ClusterEvent.IMemberEvent>(_ => { /* ignore */ });
            Receive <Broadcast <T> >(bcast =>
            {
                var version   = localVersion.Increment(myself);
                var versioned = new Versioned <T>(version, bcast.Message);
                var send      = new Send <T>(myself, myself, versioned);

                if (log.IsInfoEnabled)
                {
                    log.Info("Sending {0} to: {1}", send, string.Join(", ", members));
                }

                foreach (var member in members)
                {
                    member.Value.Forward(send);
                }

                var pendingAck = new PendingAck <T>(myself, versioned, DateTime.UtcNow, members.Keys.ToImmutableHashSet());

                this.pendingAcks  = pendingAcks.Add(pendingAck);
                this.localVersion = version;
            });
            Receive <Send <T> >(send =>
            {
                if (AlreadySeen(send.Versioned.Version))
                {
                    log.Info("Received duplicate message {0}", send);
                }
                else
                {
                    var receivers = members.Remove(send.Origin);

                    var forward = send.WithLastSeenBy(myself);
                    if (log.IsInfoEnabled)
                    {
                        log.Info("Broadcasting message {0} to: {1}", forward, string.Join(", ", receivers.Values));
                    }

                    foreach (var member in receivers.Values)
                    {
                        member.Forward(forward);
                    }

                    if (members.TryGetValue(send.LastSeenBy, out var sender))
                    {
                        sender.Tell(new SendAck(myself, send.Versioned.Version), ActorRefs.NoSender);
                    }

                    var deliver = new Deliver <T>(send.Origin, send.Versioned);
                    Self.Forward(deliver);

                    this.pendingDelivery = pendingDelivery.Add(deliver);
                    this.pendingAcks     = pendingAcks.Add(new PendingAck <T>(myself, send.Versioned, DateTime.UtcNow, receivers.Keys.ToImmutableHashSet()));
                }
            });
            Receive <SendAck>(ack =>
            {
                log.Info("Received ACK from {0} (version: {1})", Sender, ack.Version);

                var pendingAck  = this.pendingAcks.First(x => x.Versioned.Version == ack.Version);
                var membersLeft = pendingAck.Members.Remove(ack.ReplicaId);

                this.pendingAcks = pendingAcks.Remove(pendingAck);
                if (!membersLeft.IsEmpty)
                {
                    this.pendingAcks = pendingAcks.Add(pendingAck.WithMembers(membersLeft));
                }
            });
            Receive <Deliver <T> >(deliver =>
            {
                TryToCasuallyDeliver(deliver);

                remoteVersions      = remoteVersions.SetItem(deliver.Origin, deliver.Versioned.Version);
                latestStableVersion = UpdateStableVersion(remoteVersions);
            });
            Receive <Resend>(_ =>
            {
                var now     = DateTime.UtcNow;
                var builder = pendingAcks.ToBuilder();
                foreach (var ack in pendingAcks)
                {
                    if (now - ack.Timestamp > settings.RetryTimeout)
                    {
                        builder.Remove(ack);
                        var send = new Send <T>(myself, myself, ack.Versioned);
                        foreach (var replicaId in ack.Members)
                        {
                            if (members.TryGetValue(replicaId, out var member))
                            {
                                member.Tell(send, ActorRefs.NoSender);
                            }
                        }
                        builder.Add(ack.WithTimestamp(now));
                    }
                }
                pendingAcks = builder.ToImmutable();
            });
            Receive <Invitation>(invitation =>
            {
                log.Info("Received invitation from {0} (ID: {1})", invitation.ReplicatorRef, invitation.ReplicaId);
                members = members.Add(invitation.ReplicaId, invitation.ReplicatorRef);
                Context.Watch(invitation.ReplicatorRef);
            });
            Receive <StableReq>(sync =>
            {
                var reply = sync.Versions.Where(ver => latestStableVersion >= ver).ToArray();
                Sender.Tell(new StableRep(reply));
            });
            Receive <Subscribe <T> >(subscribe =>
            {
                subscribers = subscribers.Add(subscribe.Ref);
                if (subscribe.Ack != null)
                {
                    subscribe.Ref.Tell(subscribe.Ack);
                }
            });
            Receive <Unsubscribe>(unsubscribe =>
            {
                subscribers = subscribers.Remove(unsubscribe.Ref);
                if (unsubscribe.Ack != null)
                {
                    unsubscribe.Ref.Tell(unsubscribe.Ack);
                }
            });
            Receive <Terminated>(terminated =>
            {
                subscribers   = subscribers.Remove(terminated.ActorRef);
                var replicaId = members.FirstOrDefault(kv => Equals(kv.Value, terminated.ActorRef));
                members       = members.Remove(replicaId.Key);
            });

            resendTask = Context.System.Scheduler
                         .ScheduleTellOnceCancelable(settings.ResendInterval, Self, Resend.Instance, ActorRefs.NoSender);
        }
Esempio n. 20
0
 public SendAck(ReplicaId replicaId, VClock version)
 {
     ReplicaId = replicaId;
     Version   = version;
 }
Esempio n. 21
0
 public Send <T> WithLastSeenBy(ReplicaId lastSender) => new Send <T>(Origin, lastSender, Versioned);
 /// <summary>
 /// Serializes the object to JSON.
 /// </summary>
 /// <param name="writer">The <see cref="T: Newtonsoft.Json.JsonWriter" /> to write to.</param>
 /// <param name="value">The object to serialize to JSON.</param>
 public static void Serialize(JsonWriter writer, ReplicaId value)
 {
     writer.WriteValue(value.ToString());
 }
Esempio n. 23
0
 public Deliver(ReplicaId origin, Versioned <T> versioned)
 {
     Origin    = origin;
     Versioned = versioned;
 }
Esempio n. 24
0
 public Invitation(ReplicaId replicaId, IActorRef replicatorRef)
 {
     ReplicaId     = replicaId;
     ReplicatorRef = replicatorRef;
 }
Esempio n. 25
0
 public Position(int id, int replicaId)
 {
     Id        = id;
     ReplicaId = replicaId;
 }
Esempio n. 26
0
 /// <summary>
 /// Returns a local time value for target <paramref name="replicaId"/>
 /// stored in current <see cref="VClock"/>.
 /// </summary>
 public long this[ReplicaId replicaId] => Value?.GetValueOrDefault(replicaId, 0L) ?? 0L;