Commit 4e5bbd11 authored by Nick Craver's avatar Nick Craver

Documentation cleanup

parent 5b5be771
...@@ -9,11 +9,12 @@ ...@@ -9,11 +9,12 @@
namespace StackExchange.Redis.Tests namespace StackExchange.Redis.Tests
{ {
/// <summary> /// <summary>
/// Override for <see cref="Xunit.FactAttribute"/> that truncates our DisplayName down. /// <para>Override for <see cref="Xunit.FactAttribute"/> that truncates our DisplayName down.</para>
/// /// <para>
/// Attribute that is applied to a method to indicate that it is a fact that should /// Attribute that is applied to a method to indicate that it is a fact that should
/// be run by the test runner. It can also be extended to support a customized definition /// be run by the test runner. It can also be extended to support a customized definition
/// of a test method. /// of a test method.
/// </para>
/// </summary> /// </summary>
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
[XunitTestCaseDiscoverer("StackExchange.Redis.Tests.FactDiscoverer", "StackExchange.Redis.Tests")] [XunitTestCaseDiscoverer("StackExchange.Redis.Tests.FactDiscoverer", "StackExchange.Redis.Tests")]
...@@ -32,13 +33,14 @@ public override string Skip ...@@ -32,13 +33,14 @@ public override string Skip
} }
/// <summary> /// <summary>
/// Override for <see cref="Xunit.TheoryAttribute"/> that truncates our DisplayName down. /// <para>Override for <see cref="Xunit.TheoryAttribute"/> that truncates our DisplayName down.</para>
/// /// <para>
/// Marks a test method as being a data theory. Data theories are tests which are /// Marks a test method as being a data theory. Data theories are tests which are
/// fed various bits of data from a data source, mapping to parameters on the test /// fed various bits of data from a data source, mapping to parameters on the test
/// method. If the data source contains multiple rows, then the test method is executed /// method. If the data source contains multiple rows, then the test method is executed
/// multiple times (once with each data row). Data is provided by attributes which /// multiple times (once with each data row). Data is provided by attributes which
/// derive from Xunit.Sdk.DataAttribute (notably, Xunit.InlineDataAttribute and Xunit.MemberDataAttribute). /// derive from Xunit.Sdk.DataAttribute (notably, Xunit.InlineDataAttribute and Xunit.MemberDataAttribute).
/// </para>
/// </summary> /// </summary>
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
[XunitTestCaseDiscoverer("StackExchange.Redis.Tests.TheoryDiscoverer", "StackExchange.Redis.Tests")] [XunitTestCaseDiscoverer("StackExchange.Redis.Tests.TheoryDiscoverer", "StackExchange.Redis.Tests")]
......
...@@ -4,23 +4,23 @@ ...@@ -4,23 +4,23 @@
namespace StackExchange.Redis namespace StackExchange.Redis
{ {
/// <summary> /// <summary>
/// A collection of IProfiledCommands. /// <para>A collection of IProfiledCommands.</para>
/// /// <para>This is a very light weight data structure, only supporting enumeration.</para>
/// This is a very light weight data structure, only supporting enumeration. /// <para>
///
/// While it implements IEnumerable, it there are fewer allocations if one uses /// While it implements IEnumerable, it there are fewer allocations if one uses
/// it's explicit GetEnumerator() method. Using `foreach` does this automatically. /// it's explicit GetEnumerator() method. Using `foreach` does this automatically.
/// /// </para>
/// This type is not threadsafe. /// <para>This type is not threadsafe.</para>
/// </summary> /// </summary>
public struct ProfiledCommandEnumerable : IEnumerable<IProfiledCommand> public struct ProfiledCommandEnumerable : IEnumerable<IProfiledCommand>
{ {
/// <summary> /// <summary>
/// <para>
/// Implements IEnumerator for ProfiledCommandEnumerable. /// Implements IEnumerator for ProfiledCommandEnumerable.
/// This implementation is comparable to List.Enumerator and Dictionary.Enumerator, /// This implementation is comparable to List.Enumerator and Dictionary.Enumerator,
/// and is provided to reduce allocations in the common (ie. foreach) case. /// and is provided to reduce allocations in the common (ie. foreach) case.
/// /// </para>
/// This type is not threadsafe. /// <para>This type is not threadsafe.</para>
/// </summary> /// </summary>
public struct Enumerator : IEnumerator<IProfiledCommand> public struct Enumerator : IEnumerator<IProfiledCommand>
{ {
...@@ -89,10 +89,11 @@ internal ProfiledCommandEnumerable(ProfileStorage head) ...@@ -89,10 +89,11 @@ internal ProfiledCommandEnumerable(ProfileStorage head)
} }
/// <summary> /// <summary>
/// <para>
/// Returns an implementor of IEnumerator that, provided it isn't accessed /// Returns an implementor of IEnumerator that, provided it isn't accessed
/// though an interface, avoids allocations. /// though an interface, avoids allocations.
/// /// </para>
/// `foreach` will automatically use this method. /// <para>`foreach` will automatically use this method.</para>
/// </summary> /// </summary>
public Enumerator GetEnumerator() => new Enumerator(Head); public Enumerator GetEnumerator() => new Enumerator(Head);
...@@ -102,10 +103,11 @@ internal ProfiledCommandEnumerable(ProfileStorage head) ...@@ -102,10 +103,11 @@ internal ProfiledCommandEnumerable(ProfileStorage head)
} }
/// <summary> /// <summary>
/// <para>
/// A thread-safe collection tailored to the "always append, with high contention, then enumerate once with no contention" /// A thread-safe collection tailored to the "always append, with high contention, then enumerate once with no contention"
/// behavior of our profiling. /// behavior of our profiling.
/// /// </para>
/// Performs better than ConcurrentBag, which is important since profiling code shouldn't impact timings. /// <para>Performs better than ConcurrentBag, which is important since profiling code shouldn't impact timings.</para>
/// </summary> /// </summary>
internal sealed class ConcurrentProfileStorageCollection internal sealed class ConcurrentProfileStorageCollection
{ {
...@@ -137,13 +139,10 @@ internal static int CountInPool() ...@@ -137,13 +139,10 @@ internal static int CountInPool()
} }
/// <summary> /// <summary>
/// This method is thread-safe. /// <para>This method is thread-safe.</para>
/// /// <para>Adds an element to the bag.</para>
/// Adds an element to the bag. /// <para>Order is not preserved.</para>
/// /// <para>The element can only be a member of *one* bag.</para>
/// Order is not preserved.
///
/// The element can only be a member of *one* bag.
/// </summary> /// </summary>
/// <param name="command">The command to add.</param> /// <param name="command">The command to add.</param>
public void Add(ProfileStorage command) public void Add(ProfileStorage command)
...@@ -163,12 +162,12 @@ public void Add(ProfileStorage command) ...@@ -163,12 +162,12 @@ public void Add(ProfileStorage command)
} }
/// <summary> /// <summary>
/// <para>
/// This method returns an enumerable view of the bag, and returns it to /// This method returns an enumerable view of the bag, and returns it to
/// an internal pool for reuse by GetOrCreate(). /// an internal pool for reuse by GetOrCreate().
/// /// </para>
/// It is not thread safe. /// <para>It is not thread safe.</para>
/// /// <para>It should only be called once the bag is finished being mutated.</para>
/// It should only be called once the bag is finished being mutated.
/// </summary> /// </summary>
public ProfiledCommandEnumerable EnumerateAndReturnForReuse() public ProfiledCommandEnumerable EnumerateAndReturnForReuse()
{ {
...@@ -194,10 +193,11 @@ public void ReturnForReuse() ...@@ -194,10 +193,11 @@ public void ReturnForReuse()
} }
/// <summary> /// <summary>
/// Returns a ConcurrentProfileStorageCollection to use. /// <para>Returns a ConcurrentProfileStorageCollection to use.</para>
/// /// <para>
/// It *may* have allocated a new one, or it may return one that has previously been released. /// It *may* have allocated a new one, or it may return one that has previously been released.
/// To return the collection, call EnumerateAndReturnForReuse() /// To return the collection, call EnumerateAndReturnForReuse()
/// </para>
/// </summary> /// </summary>
public static ConcurrentProfileStorageCollection GetOrCreate() public static ConcurrentProfileStorageCollection GetOrCreate()
{ {
......
...@@ -10,11 +10,12 @@ public partial class ConnectionMultiplexer ...@@ -10,11 +10,12 @@ public partial class ConnectionMultiplexer
internal ProfileContextTracker profiledCommands; internal ProfileContextTracker profiledCommands;
/// <summary> /// <summary>
/// Sets an IProfiler instance for this ConnectionMultiplexer. /// <para>Sets an IProfiler instance for this ConnectionMultiplexer.</para>
/// /// <para>
/// An IProfiler instances is used to determine which context to associate an /// An IProfiler instances is used to determine which context to associate an
/// IProfiledCommand with. See BeginProfiling(object) and FinishProfiling(object) /// IProfiledCommand with. See BeginProfiling(object) and FinishProfiling(object)
/// for more details. /// for more details.
/// </para>
/// </summary> /// </summary>
/// <param name="profiler">The profiler to register.</param> /// <param name="profiler">The profiler to register.</param>
public void RegisterProfiler(IProfiler profiler) public void RegisterProfiler(IProfiler profiler)
...@@ -26,14 +27,13 @@ public void RegisterProfiler(IProfiler profiler) ...@@ -26,14 +27,13 @@ public void RegisterProfiler(IProfiler profiler)
} }
/// <summary> /// <summary>
/// Begins profiling for the given context. /// <para>Begins profiling for the given context.</para>
/// /// <para>
/// If the same context object is returned by the registered IProfiler, the IProfiledCommands /// If the same context object is returned by the registered IProfiler, the IProfiledCommands
/// will be associated with each other. /// will be associated with each other.
/// /// </para>
/// Call FinishProfiling with the same context to get the assocated commands. /// <para>Call FinishProfiling with the same context to get the assocated commands.</para>
/// /// <para>Note that forContext cannot be a WeakReference or a WeakReference&lt;T</para>&gt;
/// Note that forContext cannot be a WeakReference or a WeakReference&lt;T&gt;
/// </summary> /// </summary>
/// <param name="forContext">The context to begin profiling.</param> /// <param name="forContext">The context to begin profiling.</param>
public void BeginProfiling(object forContext) public void BeginProfiling(object forContext)
...@@ -49,9 +49,8 @@ public void BeginProfiling(object forContext) ...@@ -49,9 +49,8 @@ public void BeginProfiling(object forContext)
} }
/// <summary> /// <summary>
/// Stops profiling for the given context, returns all IProfiledCommands associated. /// <para>Stops profiling for the given context, returns all IProfiledCommands associated.</para>
/// /// <para>By default this may do a sweep for dead profiling contexts, you can disable this by passing "allowCleanupSweep: false".</para>
/// By default this may do a sweep for dead profiling contexts, you can disable this by passing "allowCleanupSweep: false".
/// </summary> /// </summary>
/// <param name="forContext">The context to begin profiling.</param> /// <param name="forContext">The context to begin profiling.</param>
/// <param name="allowCleanupSweep">Whether to allow cleanup of old profiling sessions.</param> /// <param name="allowCleanupSweep">Whether to allow cleanup of old profiling sessions.</param>
......
namespace StackExchange.Redis namespace StackExchange.Redis
{ {
/// <summary> /// <summary>
/// <para>
/// If an IProfiledCommand is a retransmission of a previous command, this enum /// If an IProfiledCommand is a retransmission of a previous command, this enum
/// is used to indicate what prompted the retransmission. /// is used to indicate what prompted the retransmission.
/// /// </para>
/// <para>
/// This can be used to distinguish between transient causes (moving hashslots, joining nodes, etc.) /// This can be used to distinguish between transient causes (moving hashslots, joining nodes, etc.)
/// and incorrect routing. /// and incorrect routing.
/// </para>
/// </summary> /// </summary>
public enum RetransmissionReasonType public enum RetransmissionReasonType
{ {
......
...@@ -4,10 +4,11 @@ ...@@ -4,10 +4,11 @@
namespace StackExchange.Redis namespace StackExchange.Redis
{ {
/// <summary> /// <summary>
/// A profiled command against a redis instance. /// <para>A profiled command against a redis instance.</para>
/// /// <para>
/// TimeSpans returned by this interface use a high precision timer if possible. /// TimeSpans returned by this interface use a high precision timer if possible.
/// DateTimes returned by this interface are no more precise than DateTime.UtcNow. /// DateTimes returned by this interface are no more precise than DateTime.UtcNow.
/// </para>
/// </summary> /// </summary>
public interface IProfiledCommand public interface IProfiledCommand
{ {
......
...@@ -6,15 +6,16 @@ ...@@ -6,15 +6,16 @@
namespace StackExchange.Redis namespace StackExchange.Redis
{ {
/// <summary> /// <summary>
/// Represents a Lua script that can be executed on Redis. /// <para>Represents a Lua script that can be executed on Redis.</para>
/// /// <para>
/// Unlike normal Redis Lua scripts, LuaScript can have named parameters (prefixed by a @). /// Unlike normal Redis Lua scripts, LuaScript can have named parameters (prefixed by a @).
/// Public fields and properties of the passed in object are treated as parameters. /// Public fields and properties of the passed in object are treated as parameters.
/// /// </para>
/// <para>
/// Parameters of type RedisKey are sent to Redis as KEY (https://redis.io/commands/eval) in addition to arguments, /// Parameters of type RedisKey are sent to Redis as KEY (https://redis.io/commands/eval) in addition to arguments,
/// so as to play nicely with Redis Cluster. /// so as to play nicely with Redis Cluster.
/// /// </para>
/// All members of this class are thread safe. /// <para>All members of this class are thread safe.</para>
/// </summary> /// </summary>
public sealed class LuaScript public sealed class LuaScript
{ {
...@@ -28,9 +29,8 @@ public sealed class LuaScript ...@@ -28,9 +29,8 @@ public sealed class LuaScript
public string OriginalScript { get; } public string OriginalScript { get; }
/// <summary> /// <summary>
/// The Lua script that will actually be sent to Redis for execution. /// <para>The Lua script that will actually be sent to Redis for execution.</para>
/// /// <para>All @-prefixed parameter names have been replaced at this point.</para>
/// All @-prefixed parameter names have been replaced at this point.
/// </summary> /// </summary>
public string ExecutableScript { get; } public string ExecutableScript { get; }
...@@ -163,10 +163,11 @@ public Task<RedisResult> EvaluateAsync(IDatabaseAsync db, object ps = null, Redi ...@@ -163,10 +163,11 @@ public Task<RedisResult> EvaluateAsync(IDatabaseAsync db, object ps = null, Redi
} }
/// <summary> /// <summary>
/// <para>
/// Loads this LuaScript into the given IServer so it can be run with it's SHA1 hash, instead of /// Loads this LuaScript into the given IServer so it can be run with it's SHA1 hash, instead of
/// passing the full script on each Evaluate or EvaluateAsync call. /// passing the full script on each Evaluate or EvaluateAsync call.
/// /// </para>
/// Note: the FireAndForget command flag cannot be set /// <para>Note: the FireAndForget command flag cannot be set</para>
/// </summary> /// </summary>
/// <param name="server">The server to load the script on.</param> /// <param name="server">The server to load the script on.</param>
/// <param name="flags">The command flags to use.</param> /// <param name="flags">The command flags to use.</param>
...@@ -182,10 +183,11 @@ public LoadedLuaScript Load(IServer server, CommandFlags flags = CommandFlags.No ...@@ -182,10 +183,11 @@ public LoadedLuaScript Load(IServer server, CommandFlags flags = CommandFlags.No
} }
/// <summary> /// <summary>
/// <para>
/// Loads this LuaScript into the given IServer so it can be run with it's SHA1 hash, instead of /// Loads this LuaScript into the given IServer so it can be run with it's SHA1 hash, instead of
/// passing the full script on each Evaluate or EvaluateAsync call. /// passing the full script on each Evaluate or EvaluateAsync call.
/// /// </para>
/// Note: the FireAndForget command flag cannot be set /// <para>Note: the FireAndForget command flag cannot be set</para>
/// </summary> /// </summary>
/// <param name="server">The server to load the script on.</param> /// <param name="server">The server to load the script on.</param>
/// <param name="flags">The command flags to use.</param> /// <param name="flags">The command flags to use.</param>
...@@ -202,21 +204,24 @@ public async Task<LoadedLuaScript> LoadAsync(IServer server, CommandFlags flags ...@@ -202,21 +204,24 @@ public async Task<LoadedLuaScript> LoadAsync(IServer server, CommandFlags flags
} }
/// <summary> /// <summary>
/// Represents a Lua script that can be executed on Redis. /// <para>Represents a Lua script that can be executed on Redis.</para>
/// /// <para>
/// Unlike LuaScript, LoadedLuaScript sends the hash of it's ExecutableScript to Redis rather than pass /// Unlike LuaScript, LoadedLuaScript sends the hash of it's ExecutableScript to Redis rather than pass
/// the whole script on each call. This requires that the script be loaded into Redis before it is used. /// the whole script on each call. This requires that the script be loaded into Redis before it is used.
/// /// </para>
/// <para>
/// To create a LoadedLuaScript first create a LuaScript via LuaScript.Prepare(string), then /// To create a LoadedLuaScript first create a LuaScript via LuaScript.Prepare(string), then
/// call Load(IServer, CommandFlags) on the returned LuaScript. /// call Load(IServer, CommandFlags) on the returned LuaScript.
/// /// </para>
/// <para>
/// Unlike normal Redis Lua scripts, LoadedLuaScript can have named parameters (prefixed by a @). /// Unlike normal Redis Lua scripts, LoadedLuaScript can have named parameters (prefixed by a @).
/// Public fields and properties of the passed in object are treated as parameters. /// Public fields and properties of the passed in object are treated as parameters.
/// /// </para>
/// <para>
/// Parameters of type RedisKey are sent to Redis as KEY (https://redis.io/commands/eval) in addition to arguments, /// Parameters of type RedisKey are sent to Redis as KEY (https://redis.io/commands/eval) in addition to arguments,
/// so as to play nicely with Redis Cluster. /// so as to play nicely with Redis Cluster.
/// /// </para>
/// All members of this class are thread safe. /// <para>All members of this class are thread safe.</para>
/// </summary> /// </summary>
public sealed class LoadedLuaScript public sealed class LoadedLuaScript
{ {
...@@ -231,9 +236,8 @@ public sealed class LoadedLuaScript ...@@ -231,9 +236,8 @@ public sealed class LoadedLuaScript
public string ExecutableScript => Original.ExecutableScript; public string ExecutableScript => Original.ExecutableScript;
/// <summary> /// <summary>
/// The SHA1 hash of ExecutableScript. /// <para>The SHA1 hash of ExecutableScript.</para>
/// /// <para>This is sent to Redis instead of ExecutableScript during Evaluate and EvaluateAsync calls.</para>
/// This is sent to Redis instead of ExecutableScript during Evaluate and EvaluateAsync calls.
/// </summary> /// </summary>
public byte[] Hash { get; } public byte[] Hash { get; }
...@@ -247,10 +251,11 @@ internal LoadedLuaScript(LuaScript original, byte[] hash) ...@@ -247,10 +251,11 @@ internal LoadedLuaScript(LuaScript original, byte[] hash)
} }
/// <summary> /// <summary>
/// Evaluates this LoadedLuaScript against the given database, extracting parameters for the passed in object if any. /// <para>Evaluates this LoadedLuaScript against the given database, extracting parameters for the passed in object if any.</para>
/// /// <para>
/// This method sends the SHA1 hash of the ExecutableScript instead of the script itself. If the script has not /// This method sends the SHA1 hash of the ExecutableScript instead of the script itself. If the script has not
/// been loaded into the passed Redis instance it will fail. /// been loaded into the passed Redis instance it will fail.
/// </para>
/// </summary> /// </summary>
/// <param name="db">The redis databse to evaluate against.</param> /// <param name="db">The redis databse to evaluate against.</param>
/// <param name="ps">The parameter object to use.</param> /// <param name="ps">The parameter object to use.</param>
...@@ -263,10 +268,11 @@ public RedisResult Evaluate(IDatabase db, object ps = null, RedisKey? withKeyPre ...@@ -263,10 +268,11 @@ public RedisResult Evaluate(IDatabase db, object ps = null, RedisKey? withKeyPre
} }
/// <summary> /// <summary>
/// Evaluates this LoadedLuaScript against the given database, extracting parameters for the passed in object if any. /// <para>Evaluates this LoadedLuaScript against the given database, extracting parameters for the passed in object if any.</para>
/// /// <para>
/// This method sends the SHA1 hash of the ExecutableScript instead of the script itself. If the script has not /// This method sends the SHA1 hash of the ExecutableScript instead of the script itself. If the script has not
/// been loaded into the passed Redis instance it will fail. /// been loaded into the passed Redis instance it will fail.
/// </para>
/// </summary> /// </summary>
/// <param name="db">The redis databse to evaluate against.</param> /// <param name="db">The redis databse to evaluate against.</param>
/// <param name="ps">The parameter object to use.</param> /// <param name="ps">The parameter object to use.</param>
......
...@@ -11,14 +11,13 @@ namespace StackExchange.Redis ...@@ -11,14 +11,13 @@ namespace StackExchange.Redis
internal sealed class ProfileContextTracker internal sealed class ProfileContextTracker
{ {
/// <summary> /// <summary>
/// Necessary, because WeakReference can't be readily comparable (since the reference is... weak). /// <para>Necessary, because WeakReference can't be readily comparable (since the reference is... weak).</para>
/// /// <para>This lets us detect leaks* with some reasonable confidence, and cleanup periodically.</para>
/// This lets us detect leaks* with some reasonable confidence, and cleanup periodically. /// <para>
///
/// Some calisthenics are done to avoid allocating WeakReferences for no reason, as often /// Some calisthenics are done to avoid allocating WeakReferences for no reason, as often
/// we're just looking up ProfileStorage. /// we're just looking up ProfileStorage.
/// /// </para>
/// * Somebody starts profiling, but for whatever reason never *stops* with a context object /// <para>* Somebody starts profiling, but for whatever reason never *stops* with a context object</para>
/// </summary> /// </summary>
private struct ProfileContextCell : IEquatable<ProfileContextCell> private struct ProfileContextCell : IEquatable<ProfileContextCell>
{ {
...@@ -47,20 +46,22 @@ private ProfileContextCell(object forObj, bool isEphemeral) ...@@ -47,20 +46,22 @@ private ProfileContextCell(object forObj, bool isEphemeral)
} }
/// <summary> /// <summary>
/// Suitable for use as a key into something. /// <para>Suitable for use as a key into something.</para>
/// /// <para>
/// This instance **WILL NOT** keep forObj alive, so it can /// This instance **WILL NOT** keep forObj alive, so it can
/// be copied out of the calling method's scope. /// be copied out of the calling method's scope.
/// </para>
/// </summary> /// </summary>
/// <param name="forObj">The object to get a context for.</param> /// <param name="forObj">The object to get a context for.</param>
public static ProfileContextCell ToStoreUnder(object forObj) => new ProfileContextCell(forObj, isEphemeral: false); public static ProfileContextCell ToStoreUnder(object forObj) => new ProfileContextCell(forObj, isEphemeral: false);
/// <summary> /// <summary>
/// Only suitable for looking up. /// <para>Only suitable for looking up.</para>
/// /// <para>
/// This instance **ABSOLUTELY WILL** keep forObj alive, so this /// This instance **ABSOLUTELY WILL** keep forObj alive, so this
/// had better not be copied into anything outside the scope of the /// had better not be copied into anything outside the scope of the
/// calling method. /// calling method.
/// </para>
/// </summary> /// </summary>
/// <param name="forObj">The object to lookup a context by.</param> /// <param name="forObj">The object to lookup a context by.</param>
public static ProfileContextCell ToLookupBy(object forObj) => new ProfileContextCell(forObj, isEphemeral: true); public static ProfileContextCell ToLookupBy(object forObj) => new ProfileContextCell(forObj, isEphemeral: true);
...@@ -130,9 +131,8 @@ public ProfileContextTracker() ...@@ -130,9 +131,8 @@ public ProfileContextTracker()
} }
/// <summary> /// <summary>
/// Registers the passed context with a collection that can be retried with subsequent calls to TryGetValue. /// <para>Registers the passed context with a collection that can be retried with subsequent calls to TryGetValue.</para>
/// /// <para>Returns false if the passed context object is already registered.</para>
/// Returns false if the passed context object is already registered.
/// </summary> /// </summary>
/// <param name="ctx">The context to use.</param> /// <param name="ctx">The context to use.</param>
public bool TryCreate(object ctx) public bool TryCreate(object ctx)
...@@ -146,10 +146,11 @@ public bool TryCreate(object ctx) ...@@ -146,10 +146,11 @@ public bool TryCreate(object ctx)
} }
/// <summary> /// <summary>
/// <para>
/// Returns true and sets val to the tracking collection associated with the given context if the context /// Returns true and sets val to the tracking collection associated with the given context if the context
/// was registered with TryCreate. /// was registered with TryCreate.
/// /// </para>
/// Otherwise returns false and sets val to null. /// <para>Otherwise returns false and sets val to null.</para>
/// </summary> /// </summary>
/// <param name="ctx">The context to get a value for.</param> /// <param name="ctx">The context to get a value for.</param>
/// <param name="val">The collection (if present) for <paramref name="ctx"/>.</param> /// <param name="val">The collection (if present) for <paramref name="ctx"/>.</param>
...@@ -160,13 +161,15 @@ public bool TryGetValue(object ctx, out ConcurrentProfileStorageCollection val) ...@@ -160,13 +161,15 @@ public bool TryGetValue(object ctx, out ConcurrentProfileStorageCollection val)
} }
/// <summary> /// <summary>
/// <para>
/// Removes a context, setting all commands to a (non-thread safe) enumerable of /// Removes a context, setting all commands to a (non-thread safe) enumerable of
/// all the commands attached to that context. /// all the commands attached to that context.
/// /// </para>
/// If the context was never registered, will return false and set commands to null. /// <para>If the context was never registered, will return false and set commands to null.</para>
/// /// <para>
/// Subsequent calls to TryRemove with the same context will return false unless it is /// Subsequent calls to TryRemove with the same context will return false unless it is
/// re-registered with TryCreate. /// re-registered with TryCreate.
/// </para>
/// </summary> /// </summary>
/// <param name="ctx">The context to remove for.</param> /// <param name="ctx">The context to remove for.</param>
/// <param name="commands">The commands to remove.</param> /// <param name="commands">The commands to remove.</param>
...@@ -219,4 +222,4 @@ public bool TryCleanup() ...@@ -219,4 +222,4 @@ public bool TryCleanup()
return true; return true;
} }
} }
} }
\ No newline at end of file
...@@ -277,19 +277,21 @@ internal static byte[] ConcatenateBytes(byte[] a, object b, byte[] c) ...@@ -277,19 +277,21 @@ internal static byte[] ConcatenateBytes(byte[] a, object b, byte[] c)
} }
/// <summary> /// <summary>
/// Prepends p to this RedisKey, returning a new RedisKey. /// <para>Prepends p to this RedisKey, returning a new RedisKey.</para>
/// /// <para>
/// Avoids some allocations if possible, repeated Prepend/Appends make /// Avoids some allocations if possible, repeated Prepend/Appends make
/// it less possible. /// it less possible.
/// </para>
/// </summary> /// </summary>
/// <param name="prefix">The prefix to prepend.</param> /// <param name="prefix">The prefix to prepend.</param>
public RedisKey Prepend(RedisKey prefix) => WithPrefix(prefix, this); public RedisKey Prepend(RedisKey prefix) => WithPrefix(prefix, this);
/// <summary> /// <summary>
/// Appends p to this RedisKey, returning a new RedisKey. /// <para>Appends p to this RedisKey, returning a new RedisKey.</para>
/// /// <para>
/// Avoids some allocations if possible, repeated Prepend/Appends make /// Avoids some allocations if possible, repeated Prepend/Appends make
/// it less possible. /// it less possible.
/// </para>
/// </summary> /// </summary>
/// <param name="suffix">The suffix to append.</param> /// <param name="suffix">The suffix to append.</param>
public RedisKey Append(RedisKey suffix) => WithPrefix(this, suffix); public RedisKey Append(RedisKey suffix) => WithPrefix(this, suffix);
......
...@@ -432,6 +432,7 @@ internal static RedisValue TryParse(object obj) ...@@ -432,6 +432,7 @@ internal static RedisValue TryParse(object obj)
/// <summary> /// <summary>
/// Creates a new <see cref="RedisValue"/> from a <see cref="T:ReadOnlyMemory{byte}"/>. /// Creates a new <see cref="RedisValue"/> from a <see cref="T:ReadOnlyMemory{byte}"/>.
/// </summary> /// </summary>
/// <param name="value">The <see cref="T:ReadOnlyMemory{byte}"/> to convert to a <see cref="RedisValue"/>.</param>
public static implicit operator RedisValue(ReadOnlyMemory<byte> value) public static implicit operator RedisValue(ReadOnlyMemory<byte> value)
{ {
if (value.Length == 0) return EmptyString; if (value.Length == 0) return EmptyString;
...@@ -440,6 +441,7 @@ internal static RedisValue TryParse(object obj) ...@@ -440,6 +441,7 @@ internal static RedisValue TryParse(object obj)
/// <summary> /// <summary>
/// Creates a new <see cref="RedisValue"/> from a <see cref="T:Memory{byte}"/>. /// Creates a new <see cref="RedisValue"/> from a <see cref="T:Memory{byte}"/>.
/// </summary> /// </summary>
/// <param name="value">The <see cref="T:Memory{byte}"/> to convert to a <see cref="RedisValue"/>.</param>
public static implicit operator RedisValue(Memory<byte> value) => (ReadOnlyMemory<byte>)value; public static implicit operator RedisValue(Memory<byte> value) => (ReadOnlyMemory<byte>)value;
/// <summary> /// <summary>
......
...@@ -272,16 +272,19 @@ private static void PrefixIfNeeded(ILGenerator il, LocalBuilder needsPrefixBool, ...@@ -272,16 +272,19 @@ private static void PrefixIfNeeded(ILGenerator il, LocalBuilder needsPrefixBool,
} }
/// <summary> /// <summary>
/// Creates a Func that extracts parameters from the given type for use by a LuaScript. /// <para>Creates a Func that extracts parameters from the given type for use by a LuaScript.</para>
/// /// <para>
/// Members that are RedisKey's get extracted to be passed in as keys to redis; all members that /// Members that are RedisKey's get extracted to be passed in as keys to redis; all members that
/// appear in the script get extracted as RedisValue arguments to be sent up as args. /// appear in the script get extracted as RedisValue arguments to be sent up as args.
/// /// </para>
/// <para>
/// We send all values as arguments so we don't have to prepare the same script for different parameter /// We send all values as arguments so we don't have to prepare the same script for different parameter
/// types. /// types.
/// /// </para>
/// <para>
/// The created Func takes a RedisKey, which will be prefixed to all keys (and arguments of type RedisKey) for /// The created Func takes a RedisKey, which will be prefixed to all keys (and arguments of type RedisKey) for
/// keyspace isolation. /// keyspace isolation.
/// </para>
/// </summary> /// </summary>
/// <param name="t">The type to extract for.</param> /// <param name="t">The type to extract for.</param>
/// <param name="script">The script to extract for.</param> /// <param name="script">The script to extract for.</param>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment