Permalink
Browse files

Add sample app to demonstrate sharding with two local servers running

  • Loading branch information...
1 parent 095d9e6 commit fc9ba4ebb83c86a010d51623e79f86c61fbcb151 @webpaul webpaul committed Apr 8, 2010
@@ -101,6 +101,25 @@ public void Can_get_single_entity_from_correct_sharded_server()
}
[Fact]
+ public void Can_get_single_entity_from_correct_sharded_server_when_location_is_unknown()
+ {
+ using (var documentStore = new ShardedDocumentStore(shardStrategy, shards).Initialise())
+ using (var session = documentStore.OpenSession())
+ {
+ //store item that goes in 2nd shard
+ session.Store(company2);
+
+ //get it, should try all shards and find it
+ shardResolution.Stub(x => x.SelectShardIdsFromData(null)).IgnoreArguments().Return(null);
+ shardStrategy.Stub(x => x.ShardAccessStrategy).Return(new SequentialShardAccessStrategy());
+ var loadedCompany = session.Load<Company>(company2.Id);
+
+ Assert.NotNull(loadedCompany);
+ Assert.Equal(company2.Name, loadedCompany.Name);
+ }
+ }
+
+ [Fact]
public void Can_get_all_sharded_entities()
{
using (var documentStore = new ShardedDocumentStore(shardStrategy, shards).Initialise())
@@ -6,6 +6,7 @@
using Newtonsoft.Json.Linq;
using Raven.Database.Data;
using System;
+using Raven.Database;
namespace Raven.Client
{
@@ -26,7 +27,21 @@ public DocumentSession(DocumentStore documentStore, IDatabaseCommands database)
public T Load<T>(string id)
{
- var documentFound = database.Get(id);
+ JsonDocument documentFound = null;
+
+ try
+ {
+ documentFound = database.Get(id);
+ }
+ catch (System.Net.WebException ex)
+ {
+ //Status is ProtocolError, couldn't find a better way to trap 404 which shouldn't be an exception
+ if (ex.Message == "The remote server returned an error: (404) Not Found.")
+ return default(T);
+ else
+ throw;
+ }
+
var jsonString = Encoding.UTF8.GetString(documentFound.Data);
var entity = ConvertToEntity<T>(id, jsonString);
entities.Add(entity);
@@ -82,6 +82,7 @@
<Compile Include="Document\IDocumentStore.cs" />
<Compile Include="Shard\ShardStrategy\ShardAccess\IShardAccessStrategy.cs" />
<Compile Include="Shard\ShardStrategy\ShardAccess\ParallelShardAccessStrategy.cs" />
+ <Compile Include="Shard\ShardStrategy\ShardResolution\AllShardsResolutionStrategy.cs" />
<Compile Include="Shard\ShardStrategy\ShardResolution\IShardResolutionStrategy.cs" />
<Compile Include="Shard\ShardStrategy\ShardSelection\IShardSelectionStrategy.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
@@ -0,0 +1,16 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Raven.Client.Shard
+{
+ public class AllShardsResolutionStrategy : IShardResolutionStrategy
+ {
+ public IList<string> SelectShardIdsFromData(ShardResolutionStrategyData srsd)
+ {
+ //will force it to use all shards
+ return null;
+ }
+ }
+}
@@ -30,17 +30,45 @@ public ShardedDocumentSession(IShardStrategy shardStrategy, params IDocumentSess
public T Load<T>(string id)
{
- var shardIds = shardStrategy.ShardResolutionStrategy.SelectShardIdsFromData(ShardResolutionStrategyData.BuildFrom(typeof(T)));
+ var shardIds = shardStrategy.ShardResolutionStrategy.SelectShardIdsFromData(ShardResolutionStrategyData.BuildFrom(typeof(T))) ?? new string[] { };
- if (shardIds == null || shardIds.Count == 0) throw new ApplicationException("Unable to resolve shard from type " + typeof(T).Name);
+ IDocumentSession[] shardsToUse = shardSessions.Where(x => shardIds.Contains(x.StoreIdentifier)).ToArray();
- if (shardIds.Count > 1) throw new ApplicationException("Can't resolve type " + typeof(T).Name + " for single entity load, resolved multiple shards");
+ //default to all sessions if none found to use
+ if (shardIds == null || shardIds.Count == 0)
+ shardsToUse = shardSessions;
- var shardSession = GetSingleShardSession(shardIds[0]);
-
- return shardSession.Load<T>(id);
+ //if we can narrow down to single shard, explicitly call it
+ if (shardsToUse.Length == 1)
+ {
+ return shardsToUse[0].Load<T>(id);
+ }
+ else //otherwise use access strategy to access all of them and return first one
+ {
+ var results = shardStrategy.ShardAccessStrategy.Apply<T>(shardsToUse, x =>
+ {
+ var result = x.Load<T>(id);
+
+ if (result == null)
+ return new T[] { };
+ else
+ return new[] { result };
+ });
+
+ if (results == null || results.Count == 0)
+ return default(T);
+ else
+ return results[0];
+ }
}
+ private IDocumentSession GetSingleShardSession(string shardId)
+ {
+ var shardSession = shardSessions.Where(x => x.StoreIdentifier == shardId).FirstOrDefault();
+ if (shardSession == null) throw new ApplicationException("Can't find single shard with identifier: " + shardId);
+ return shardSession;
+ }
+
public void StoreAll<T>(IEnumerable<T> entities)
{
foreach (var entity in entities)
@@ -59,13 +87,6 @@ private void SingleShardAction<T>(T entity, Action<IDocumentSession> action)
action(shardSession);
}
- private IDocumentSession GetSingleShardSession(string shardId)
- {
- var shardSession = shardSessions.Where(x => x.StoreIdentifier == shardId).FirstOrDefault();
- if (shardSession == null) throw new ApplicationException("Can't find single shard with identifier: " + shardId);
- return shardSession;
- }
-
public void Store<T>(T entity)
{
SingleShardAction(entity, shard => shard.Store(entity));
@@ -42,13 +42,18 @@ public SimpleIndex(Directory directory, string name) : base(directory, name)
{
indexWriter.DeleteDocuments(new Term("__document_id", newDocId));
}
- var luceneDoc = new Document();
- luceneDoc.Add(new Field("__document_id", newDocId, Field.Store.YES, Field.Index.UN_TOKENIZED));
- currentId = newDocId;
- CopyFieldsToDocumentButRemoveDuplicateValues(luceneDoc, fields);
+ if (newDocId != null)
+ {
+ var luceneDoc = new Document();
+ luceneDoc.Add(new Field("__document_id", newDocId, Field.Store.YES, Field.Index.UN_TOKENIZED));
+
+ currentId = newDocId;
+ CopyFieldsToDocumentButRemoveDuplicateValues(luceneDoc, fields);
+
+ indexWriter.AddDocument(luceneDoc);
+ }
- indexWriter.AddDocument(luceneDoc);
actions.IncrementSuccessIndexing();
}
@@ -0,0 +1,16 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Raven.Client.Shard;
+using Raven.Client;
+
+namespace Raven.Sample.ShardClient
+{
+ public class Company
+ {
+ public string Id { get; set; }
+ public string Name { get; set; }
+ public string Region { get; set; }
+ }
+}
@@ -0,0 +1,36 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Raven.Client.Shard;
+using Raven.Client;
+
+namespace Raven.Sample.ShardClient
+{
+ class Program
+ {
+ static void Main(string[] args)
+ {
+ var shards = new Shards {
+ new DocumentStore("localhost", 8080) { Identifier="Shard1" },
+ new DocumentStore("localhost", 8081) { Identifier="Shard2" }
+ };
+
+ using (var documentStore = new ShardedDocumentStore(new ShardStrategy(), shards).Initialise())
+ using (var session = documentStore.OpenSession())
+ {
+ //store 2 items in the 2 shards
+ session.StoreAll(new[] {
+ new Company { Name = "Company 1", Region="A" },
+ new Company { Name = "Company 2", Region="B" },
+ });
+
+ //get all, should automagically retrieve from each shard
+ var allCompanies = session.GetAll<Company>();
+
+ foreach(var company in allCompanies)
+ Console.WriteLine(company.Name);
+ }
+ }
+ }
+}
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
+ <ProductVersion>8.0.30703</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{B40059BD-5E50-4855-8EE1-1576E007E5F4}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Raven.Sample.ShardClient</RootNamespace>
+ <AssemblyName>Raven.Sample.ShardClient</AssemblyName>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ <TargetFrameworkProfile>
+ </TargetFrameworkProfile>
+ <FileAlignment>512</FileAlignment>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
+ <PlatformTarget>x86</PlatformTarget>
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
+ <PlatformTarget>x86</PlatformTarget>
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Company.cs" />
+ <Compile Include="Program.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="ShardSelectionByRegion.cs" />
+ <Compile Include="ShardStrategy.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="app.config" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\Raven.Client\Raven.Client.csproj">
+ <Project>{9F92FD36-60B6-4655-B8C6-00125B46AB6A}</Project>
+ <Name>Raven.Client</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- 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.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project>
@@ -0,0 +1,29 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Raven.Client.Shard;
+using Raven.Client;
+
+namespace Raven.Sample.ShardClient
+{
+ public class ShardSelectionByRegion : IShardSelectionStrategy
+ {
+ public string SelectShardIdForNewObject(object obj)
+ {
+ var company = obj as Company;
+ if (company != null)
+ {
+ switch (company.Region)
+ {
+ case "A":
+ return "Shard1";
+ case "B":
+ return "Shard2";
+ }
+ }
+
+ return null;
+ }
+ }
+}
@@ -0,0 +1,41 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Raven.Client.Shard;
+using Raven.Client;
+using Raven.Client.Shard.ShardStrategy.ShardAccess;
+
+namespace Raven.Sample.ShardClient
+{
+ public class ShardStrategy : IShardStrategy
+ {
+ private IShardSelectionStrategy _ShardSelectionStrategy = new ShardSelectionByRegion();
+ public IShardSelectionStrategy ShardSelectionStrategy
+ {
+ get
+ {
+ return _ShardSelectionStrategy;
+ }
+ }
+
+ //since we are using all shards for companies, always search all shards
+ private IShardResolutionStrategy _ShardResolutionStrategy = new AllShardsResolutionStrategy();
+ public IShardResolutionStrategy ShardResolutionStrategy
+ {
+ get
+ {
+ return _ShardResolutionStrategy;
+ }
+ }
+
+ private IShardAccessStrategy _ShardAccessStrategy = new ParallelShardAccessStrategy();
+ public IShardAccessStrategy ShardAccessStrategy
+ {
+ get
+ {
+ return _ShardAccessStrategy;
+ }
+ }
+ }
+}
@@ -0,0 +1,3 @@
+<?xml version="1.0"?>
+<configuration>
+<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/></startup></configuration>
@@ -5,5 +5,6 @@
<add key="IndexingBatchSize" value="100"/>
<add key="RavenDataDir" value="..\..\..\Data"/>
<add key="RavenWebDir" value="..\..\WebUI"/>
+ <add key="AnonymousAccess" value="All"/>
</appSettings>
</configuration>
Oops, something went wrong.

0 comments on commit fc9ba4e

Please sign in to comment.